textrendering/word/SRC/WPOUTLNE.CPP
changeset 0 1fb32624e06b
equal deleted inserted replaced
-1:000000000000 0:1fb32624e06b
       
     1 /*
       
     2 * Copyright (c) 1997-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 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <badesca.h>
       
    20 #include <eikenv.h>
       
    21 #include <eikappui.h>
       
    22 #include <eikon.mbg>
       
    23 
       
    24 #include "WPOUTLNE.H"
       
    25 #include <word.rsg>
       
    26 #include <word.mbg>
       
    27 
       
    28 
       
    29 const TInt KExpandedBitmapIndex = 0;
       
    30 const TInt KClosedBitmapIndex = 1;
       
    31 const TInt KIndentPerLevel=12;
       
    32 const TInt KMaxParagraphLength = 128;  // If a paragraph is longer than this length, truncate it
       
    33 const TInt KWaitingTime = 500000;
       
    34 
       
    35 
       
    36 
       
    37 
       
    38 // TOutlineEntry - constructors
       
    39 ////////////////
       
    40 
       
    41 TOutlineEntry::TOutlineEntry(TInt aParagraphNo, TInt aOutlineLevel, TInt aParaLen, TInt aParaPos, TBool aChild, TBool aLast)
       
    42 	: iParagraphNo(aParagraphNo),
       
    43 	iOutlineLevel(aOutlineLevel),
       
    44 	iParagraphLength(aParaLen),
       
    45 	iParagraphPos(aParaPos),
       
    46 	iIsChild(aChild),
       
    47 	iLastEntry(aLast)
       
    48 {
       
    49 }
       
    50 
       
    51 
       
    52 TOutlineEntry::TOutlineEntry()
       
    53 	: iParagraphNo(0),
       
    54 	iOutlineLevel(0),
       
    55 	iParagraphLength(0),
       
    56 	iParagraphPos(0),
       
    57 	iIsChild(EFalse),
       
    58 	iLastEntry(EFalse)
       
    59 {
       
    60 }
       
    61 
       
    62 // TOutlineMap - constructor
       
    63 //////////////
       
    64 
       
    65 TOutlineMap::TOutlineMap(TInt aIndex, CHierListItem* aPtr)
       
    66 	: iIndex(aIndex),
       
    67 	iPtr(aPtr)
       
    68 {
       
    69 }
       
    70 
       
    71 
       
    72 // COutlineMap
       
    73 //////////////
       
    74 
       
    75 COutlineMap* COutlineMap::NewL()
       
    76 {
       
    77 	COutlineMap* self = new(ELeave) COutlineMap();
       
    78 	CleanupStack::PushL(self);
       
    79 	self->ConstructL();
       
    80 	CleanupStack::Pop();
       
    81 	return self;
       
    82 }
       
    83 
       
    84 
       
    85 void COutlineMap::ConstructL()
       
    86 {
       
    87 	// Create table with granularity of 5
       
    88 	iOutlineMapTable=new(ELeave) COutlineMapTable(5);
       
    89 }
       
    90 
       
    91 COutlineMap::~COutlineMap()
       
    92 {
       
    93 	// delete the table
       
    94 	delete iOutlineMapTable;
       
    95 }
       
    96 
       
    97 
       
    98 void COutlineMap::BindL(TInt aRef, CHierListItem* aPtr)
       
    99 {
       
   100 	TOutlineMap entry(aRef, aPtr);
       
   101 
       
   102 	// Check to see if either of these already exists
       
   103 	// When re-expanding elements, the same references can be bound to
       
   104 	// different pointers, and the same pointers can be bound to different
       
   105 	// references.
       
   106 
       
   107 	TInt items = iOutlineMapTable->Count();
       
   108 	TInt count;
       
   109 
       
   110 	for (count = 0; count<items; count++)
       
   111 	{
       
   112 		TOutlineMap* entry = &(*iOutlineMapTable)[count];
       
   113 		if (entry->iPtr == aPtr || entry->iIndex == aRef) 
       
   114 		{
       
   115 			iOutlineMapTable->Delete(count);
       
   116 			items--;
       
   117 			count--;
       
   118 		}
       
   119 	}
       
   120 
       
   121 	iOutlineMapTable->AppendL(entry);
       
   122 }
       
   123 
       
   124 
       
   125 TInt COutlineMap::Index(CHierListItem* aPtr)
       
   126 {
       
   127 	// Given an item pointer from the list box, return an index into the
       
   128 	// Outline Table, or -1 if it does not exist
       
   129 
       
   130 	const TInt items = iOutlineMapTable->Count();
       
   131 	TInt count;
       
   132 
       
   133 	for (count=0; count<items; count++)
       
   134 	{
       
   135 		TOutlineMap* entry = &(*iOutlineMapTable)[count];
       
   136 		if (entry->iPtr == aPtr) return entry->iIndex;
       
   137 	}
       
   138 	return KErrNotFound;
       
   139 }
       
   140 
       
   141 
       
   142 CHierListItem* COutlineMap::Ptr(TInt aIndex)
       
   143 {
       
   144 	// Given an index into the Outline table, return a pointer to its
       
   145 	// entry in the list box, or NULL if it does not exist
       
   146 
       
   147 	const TInt items = iOutlineMapTable->Count();
       
   148 	TInt count;
       
   149 
       
   150 	for (count=0; count<items; count++)
       
   151 	{
       
   152 		TOutlineMap* entry = &(*iOutlineMapTable)[count];
       
   153 		if (entry->iIndex == aIndex) return entry->iPtr;
       
   154 	}
       
   155 	return NULL;
       
   156 }
       
   157 
       
   158 TBool COutlineMap::IndexPresent(TInt aIndex)
       
   159 {
       
   160 	// Returns ETrue if the given index is present in the table
       
   161 
       
   162 	TInt items = iOutlineMapTable->Count();
       
   163 	TInt count;
       
   164 
       
   165 	for (count=0; count<items; count++)
       
   166 	{
       
   167 		TOutlineMap* entry = &(*iOutlineMapTable)[count];
       
   168 		if (entry->iIndex == aIndex) return ETrue;
       
   169 	}
       
   170 	return EFalse;
       
   171 
       
   172 }
       
   173 
       
   174 
       
   175 
       
   176 /// COutlineHListBox 
       
   177 ////////////////////
       
   178 
       
   179 
       
   180 COutlineHListBox::COutlineHListBox(CRichText* aText, TInt aCursorPos)
       
   181 	: iText(aText),
       
   182 	iCursorPos(aCursorPos)
       
   183 {
       
   184 }
       
   185 
       
   186 
       
   187 TSize COutlineHListBox::MinimumSize()
       
   188 	{
       
   189 	// Specify the minimum size of this control 
       
   190 	// Essential to make the control visible
       
   191 	TSize size(iSize.iWidth, iSize.iHeight);
       
   192 	if (!(iListBoxFlags&EScrollBarSizeExcluded) && iSBFrame && iSBFrame->HScrollBarVisibility()!=CEikScrollBarFrame::EOff)
       
   193 		size.iHeight += CEikScrollBar::DefaultScrollBarBreadth();
       
   194 	size+=iBorder.SizeDelta();
       
   195 	return size;
       
   196 	}
       
   197 
       
   198 
       
   199 void COutlineHListBox::ConstructFromResourceL(TResourceReader& aReader)
       
   200 {
       
   201 	 // Called when creating the control from a dialog
       
   202 	// Reads the size of the control, then constructs the object
       
   203 	iSize.iWidth = aReader.ReadInt16();
       
   204 	iSize.iHeight = aReader.ReadInt16();
       
   205 
       
   206 	ConstructL();
       
   207 
       
   208 }
       
   209 
       
   210 
       
   211 void COutlineHListBox::ConstructL()
       
   212 	{
       
   213 	// The NewL constructor will leave if there is nothing to show in outline view,
       
   214 	// so trap it, display a message, and leave without any error
       
   215 
       
   216 	TRAPD(ret, iModel = COutlineHListBoxModel::NewL(this, iText);)
       
   217 	if (ret == KErrNoOutline)
       
   218 	{
       
   219 		CEikonEnv::Static()->InfoMsg(R_WORD_NO_OUTLINE);
       
   220 		User::Leave(KErrNone);
       
   221 	}
       
   222 
       
   223 	//  Get the open/close icons from the system
       
   224 	TFileName resource = _L("*");
       
   225 	CGulIcon* icon = iEikonEnv->CreateIconL(resource, EMbmWordOpenfdr);
       
   226 	CleanupStack::PushL(icon);
       
   227 
       
   228 	CArrayPtrFlat<CGulIcon>* icons = new(ELeave) CArrayPtrFlat<CGulIcon>(2);
       
   229 	CleanupStack::PushL(icons);
       
   230 
       
   231 	icons->AppendL(icon);
       
   232 	icon = iEikonEnv->CreateIconL(resource, EMbmWordClsdfdr);
       
   233 
       
   234 	CleanupStack::PushL(icon);
       
   235 	icons->AppendL(icon);
       
   236 	
       
   237 	iItemDrawer = new(ELeave) COutlineHListItemDrawer((COutlineHListBoxModel*)iModel, iEikonEnv->NormalFont(), icons);
       
   238 
       
   239 	CleanupStack::Pop(3);  // Cleanup the two icons and the array
       
   240 
       
   241 	// Create the initial entries of the list box
       
   242 	OutlineModel()->CreateRootListL();
       
   243 
       
   244 	CreateViewL();
       
   245 
       
   246 	// Expand the tree to show the current cursor position
       
   247 	TInt item = OutlineModel()->ExpandCurrentPositionL(iCursorPos);
       
   248 
       
   249 	if (item != -1)
       
   250 		{
       
   251 		// This updates the view to show the requested item no.
       
   252 		iView->SetCurrentItemIndex(item);
       
   253 		iView->SelectItemL(item);
       
   254 		iListBoxFlags |= EStateChanged;
       
   255 		}
       
   256 
       
   257 	CreateScrollBarFrameL();
       
   258 	ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto);
       
   259 	}
       
   260 
       
   261 
       
   262 CListBoxView* COutlineHListBox::MakeViewClassInstanceL()
       
   263 	{
       
   264 	return (new(ELeave) COutlineHListBoxView);
       
   265 	}
       
   266 
       
   267 
       
   268 TKeyResponse COutlineHListBox::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
       
   269 {
       
   270 	TInt currentItemIndex = iView->CurrentItemIndex();
       
   271 	COutlineHListBoxModel* listModel = (COutlineHListBoxModel*)iModel;
       
   272 	CHierListItem* itemToBeExpanded=listModel->Item(currentItemIndex);
       
   273 
       
   274 	TInt keyCode = aKeyEvent.iCode;
       
   275 
       
   276 	TBool expandKey = (keyCode == EKeyRightArrow || keyCode == '+');
       
   277 	TBool collapseKey = (keyCode == EKeyLeftArrow || keyCode == '-');
       
   278 
       
   279 	const TInt index=CurrentItemIndex();
       
   280 	CArrayFix<CHierListItem*>* listArray=HlModel()->HierListArray();
       
   281 	TBool itemHasChildren=EFalse;
       
   282 
       
   283 
       
   284 	if (expandKey)
       
   285 	{
       
   286 		if (!itemToBeExpanded->IsExpanded()) 
       
   287 		{
       
   288 			listModel->ExpandItemL(index);
       
   289 			CArrayFix<CHierListItem*>* newListArray=HlModel()->HierListArray();
       
   290 			if (index<newListArray->Count()-1)
       
   291 				itemHasChildren=((*newListArray)[index]->Level()==(*newListArray)[index+1]->Level()-1);
       
   292 
       
   293 		}
       
   294 	}
       
   295 
       
   296 	if (collapseKey)
       
   297 	{	
       
   298 		if (itemToBeExpanded->IsExpanded()) 
       
   299 		{
       
   300 			if (index<HlModel()->NumberOfItems()-1)
       
   301 				itemHasChildren=((*listArray)[index]->Level()==(*listArray)[index+1]->Level()-1);
       
   302 			listModel->CollapseItem(index);
       
   303 
       
   304 		}
       
   305 	}
       
   306 
       
   307 	if (expandKey || collapseKey)
       
   308 	{
       
   309 		iView->CalcDataWidth();
       
   310 		iView->CalcBottomItemIndex();
       
   311 		UpdateScrollBarsL();
       
   312 		if (itemHasChildren)
       
   313 			((CHierarchicalListBoxView*)iView)->DrawFromItem(index);
       
   314 		else
       
   315 			((CHierarchicalListBoxView*)iView)->DrawItem(index);
       
   316 		ReportListBoxEventL(MEikListBoxObserver::EEventItemActioned);
       
   317 
       
   318 		return EKeyWasConsumed;
       
   319 	}
       
   320 
       
   321 	return CEikHierarchicalListBox::OfferKeyEventL(aKeyEvent,aType);
       
   322 	
       
   323 }
       
   324 
       
   325 
       
   326 
       
   327 void COutlineHListBox::ExpandAllItemsL()
       
   328 {
       
   329 	CEikonEnv* eikonEnv=CEikonEnv::Static();
       
   330 	eikonEnv->BusyMsgL(R_WORD_EXPAND_OUTLINE, KWaitingTime);
       
   331 
       
   332 	COutlineHListBoxModel* listModel = (COutlineHListBoxModel*)iModel;
       
   333 	TInt originalIndex = CurrentItemIndex();
       
   334 	CHierListItem* itemPtr=listModel->Item(originalIndex);
       
   335 	TInt paragraphIndex = listModel->iOutlineMap->Index(itemPtr);
       
   336 
       
   337 	TInt item=0;
       
   338 
       
   339 
       
   340 
       
   341 	TInt index = 0;
       
   342 	iView->SetCurrentItemIndex(0);
       
   343 
       
   344 	while (index < listModel->NumberOfItems() )
       
   345 	{
       
   346 		CArrayFix<CHierListItem*>* listArray=listModel->HierListArray();
       
   347 		if (!(*listArray)[index]->IsExpanded())
       
   348 			{
       
   349 			listModel->ExpandItemL(index);
       
   350 			CArrayFix<CHierListItem*>* newListArray=listModel->HierListArray();
       
   351 			}
       
   352 		item = listModel->GetItemByParagraph(paragraphIndex);
       
   353 		iView->SetCurrentItemIndex(item);
       
   354 
       
   355 		index++;
       
   356 	}
       
   357 
       
   358 
       
   359 	iView->CalcDataWidth();
       
   360 	iView->CalcBottomItemIndex();
       
   361 
       
   362 	item = listModel->GetItemByParagraph(paragraphIndex);
       
   363 	((CHierarchicalListBoxView*)iView)->ScrollToMakeItemVisible(item);
       
   364 	((CHierarchicalListBoxView*)iView)->DrawFromItem(iView->TopItemIndex());
       
   365 
       
   366 	UpdateScrollBarsL();
       
   367 	ReportListBoxEventL(MEikListBoxObserver::EEventItemActioned);
       
   368 
       
   369 	eikonEnv->BusyMsgCancel();
       
   370 
       
   371 }
       
   372 
       
   373 void COutlineHListBox::CollapseAllItemsL()
       
   374 {
       
   375 
       
   376 	CEikonEnv* eikonEnv=CEikonEnv::Static();
       
   377 	eikonEnv->BusyMsgL(R_WORD_COLLAPSE_OUTLINE, KWaitingTime);
       
   378 
       
   379 	COutlineHListBoxModel* listModel = (COutlineHListBoxModel*)iModel;
       
   380 	TInt originalIndex = CurrentItemIndex();
       
   381     CHierListItem* itemPtr=listModel->Item(originalIndex);
       
   382 	TInt paragraphIndex = listModel->iOutlineMap->Index(itemPtr);
       
   383 
       
   384 	//TInt itemCount = listModel->NumberOfItems();
       
   385 	TInt index = 0;
       
   386 	TInt item = 0;
       
   387 
       
   388 	// Get root parent of this node
       
   389 	TInt rootParent = 0;
       
   390 	TInt whilecount = 0;
       
   391 
       
   392 	TInt childCount = 0;
       
   393 
       
   394 	while (whilecount<=paragraphIndex)
       
   395 	{
       
   396 		if (listModel->iOutlineTable->At(whilecount).iIsChild)
       
   397 			childCount++;
       
   398 
       
   399 		if (childCount==0)
       
   400 			rootParent = whilecount;
       
   401 
       
   402 		if (listModel->iOutlineTable->At(whilecount).iLastEntry)
       
   403 			childCount--;
       
   404 
       
   405 		whilecount++;
       
   406 	}
       
   407 
       
   408 	
       
   409 
       
   410 	while (index < listModel->NumberOfItems() )
       
   411 	{
       
   412 		CArrayFix<CHierListItem*>* listArray=listModel->HierListArray();
       
   413 	if ((*listArray)[index]->IsExpanded())
       
   414 		{
       
   415 		HlModel()->CollapseItem(index);
       
   416 		}
       
   417 
       
   418 		item = listModel->GetItemByParagraph(rootParent);
       
   419 		iView->SetCurrentItemIndex(item);
       
   420 
       
   421 
       
   422 		index++;
       
   423 	}
       
   424 
       
   425 	iView->CalcDataWidth();
       
   426 	iView->CalcBottomItemIndex();
       
   427 
       
   428 	item = listModel->GetItemByParagraph(paragraphIndex);
       
   429 	((CHierarchicalListBoxView*)iView)->ScrollToMakeItemVisible(item);
       
   430 	((CHierarchicalListBoxView*)iView)->DrawFromItem(iView->TopItemIndex());
       
   431 				
       
   432 	UpdateScrollBarsL();
       
   433 	ReportListBoxEventL(MEikListBoxObserver::EEventItemActioned);
       
   434 
       
   435 	eikonEnv->BusyMsgCancel();
       
   436 
       
   437 }
       
   438 
       
   439 
       
   440 
       
   441 
       
   442 // COutlineHListItemDrawer
       
   443 //////////////////////////
       
   444 
       
   445 COutlineHListItemDrawer::COutlineHListItemDrawer(COutlineHListBoxModel* aModel, const CFont* aFont,	CArrayPtrFlat<CGulIcon>* aIcons)
       
   446 	: CHierarchicalListItemDrawer(aModel, aFont, aIcons)
       
   447 	{}
       
   448 
       
   449 CGulIcon* COutlineHListItemDrawer::ItemIcon(TInt aItemIndex) const
       
   450 	{
       
   451 	if (!iIconArray || aItemIndex <= -1 || aItemIndex >= iModel->NumberOfItems())
       
   452 		return NULL;
       
   453 	TInt iconIndex;
       
   454 
       
   455 	COutlineHListBoxModel* listModel = (COutlineHListBoxModel*)iModel;
       
   456     CHierListItem* itemPtr = listModel->Item(aItemIndex);
       
   457 	TInt paragraphIndex = listModel->iOutlineMap->Index(itemPtr);
       
   458 
       
   459 	iconIndex = KClosedBitmapIndex;
       
   460 
       
   461 	if (paragraphIndex < listModel->iOutlineTable->Count() - 1)
       
   462 	{
       
   463 		if (listModel->iOutlineTable->At(paragraphIndex+1).iIsChild)
       
   464 			iconIndex = KExpandedBitmapIndex;
       
   465 	}
       
   466 	return (*iIconArray)[iconIndex];
       
   467 	}
       
   468 
       
   469 
       
   470 // COutlineHListBoxView
       
   471 ////////////////////////
       
   472 
       
   473 
       
   474 TInt COutlineHListBoxView::GetParagraphLevel(CHierListItem* aItem) const
       
   475 {
       
   476 	COutlineHListBoxModel* listModel = (COutlineHListBoxModel*)iModel;
       
   477 	TInt paragraphIndex = listModel->iOutlineMap->Index(aItem);
       
   478 	if (paragraphIndex != KErrNotFound)
       
   479 	    return (listModel->iOutlineTable->At(paragraphIndex).iOutlineLevel);
       
   480 	else 
       
   481 		return 0;
       
   482 }
       
   483 
       
   484 
       
   485 void COutlineHListBoxView::DrawItem(TInt aItemIndex) const
       
   486 	{
       
   487 	// Modify this items level so that it is draw offset according to its doc level
       
   488 
       
   489 	COutlineHListBoxModel* listModel = (COutlineHListBoxModel*)iModel;
       
   490 
       
   491 	CHierListItem* itemToBeDrawn = listModel->Item(aItemIndex);
       
   492 	TInt paragraphLevel = GetParagraphLevel(itemToBeDrawn) - 1;
       
   493 
       
   494 	if (RedrawDisabled())
       
   495 		return;
       
   496 	const TInt count = iModel->NumberOfItems();
       
   497 
       
   498 	if (aItemIndex >= 0 && aItemIndex < count && ItemIsVisible(aItemIndex))
       
   499 		{
       
   500 		iGc->SetClippingRect(iViewRect);
       
   501 		const TSize itemSize = ItemSize(aItemIndex, paragraphLevel);
       
   502 		iItemDrawer->SetItemCellSize(itemSize);
       
   503 		ClearPreceedingItemRect(aItemIndex, paragraphLevel);
       
   504 		const TPoint pos=ItemPos(aItemIndex, paragraphLevel);
       
   505 		TPoint markPos(iViewRect.iTl.iX, pos.iY);
       
   506 		iItemDrawer->DrawItemMark(ItemIsSelected(aItemIndex), iFlags & EDimmed,markPos);
       
   507 
       
   508 		DrawItemLinks(aItemIndex, paragraphLevel);
       
   509 
       
   510 		STATIC_CAST(CHierarchicalListItemDrawer*, iItemDrawer)->DrawActualItem(aItemIndex, TRect(pos,itemSize),
       
   511 										aItemIndex == iCurrentItemIndex, iFlags & EEmphasized, iFlags & EDimmed, ItemIsSelected(aItemIndex));
       
   512 		iGc->CancelClippingRect();
       
   513 		}		
       
   514 	}
       
   515 
       
   516 
       
   517 TSize COutlineHListBoxView::ItemSize(TInt aItemIndex, TInt aParagraphLevel) const
       
   518 	{
       
   519 	COutlineHListBoxModel* listModel = (COutlineHListBoxModel*)iModel;
       
   520 
       
   521 	if (! listModel->Item(aItemIndex))
       
   522 		return TSize(0, 0);
       
   523 	const TInt indent=aParagraphLevel*KIndentPerLevel;
       
   524 	return TSize(Max(iViewRect.Width()-indent, DataWidth()), iItemHeight);
       
   525 	}
       
   526 
       
   527 TPoint COutlineHListBoxView::ItemPos(TInt aItemIndex, TInt aParagraphLevel) const
       
   528 	{
       
   529 	// assumes aItemIndex is currently visible
       
   530 	TInt indentLevel=0;
       
   531 	COutlineHListBoxModel* listModel = (COutlineHListBoxModel*)iModel;
       
   532 
       
   533 	if (aItemIndex>-1 && aItemIndex<listModel->NumberOfItems())
       
   534 		indentLevel=aParagraphLevel;
       
   535 	TPoint pos(-iHScrollOffset + iViewRect.iTl.iX + indentLevel*KIndentPerLevel,
       
   536 					iViewRect.iTl.iY + (aItemIndex-iTopItemIndex)*iItemHeight);
       
   537 	return pos;
       
   538 	}
       
   539 
       
   540 void COutlineHListBoxView::ClearPreceedingItemRect(TInt aItemIndex, TInt aParagraphLevel) const
       
   541 	{
       
   542 	const TInt indentLevel=aParagraphLevel;
       
   543 	TPoint startPoint=ItemPos(aItemIndex, aParagraphLevel);
       
   544 	startPoint.iX-=indentLevel*KIndentPerLevel;
       
   545 	const TRect blankRect(startPoint,TPoint(startPoint.iX+indentLevel*KIndentPerLevel,startPoint.iY+iItemHeight));
       
   546 	iItemDrawer->ClearRect(blankRect);
       
   547 	}
       
   548 
       
   549 
       
   550 void COutlineHListBoxView::DrawItemLinks(TInt aItemIndex, TInt aParagraphLevel) const
       
   551 	{
       
   552 	
       
   553 	COutlineHListBoxModel* listModel = (COutlineHListBoxModel*)iModel;
       
   554 	
       
   555 	CHierListItem* itemToBeDrawn=listModel->Item(aItemIndex);
       
   556 	const TInt itemLevel=itemToBeDrawn->Level();
       
   557 	if (!itemLevel)
       
   558 		return;
       
   559 	TPoint startPoint=ItemPos(aItemIndex, itemLevel);
       
   560 
       
   561 	TInt parentLevel = itemLevel;
       
   562 
       
   563 	CHierListItem* parent = itemToBeDrawn->Parent();
       
   564 	if (parent)
       
   565 	{
       
   566 		parentLevel = GetParagraphLevel(parent);
       
   567 		startPoint=ItemPos(aItemIndex, parentLevel);
       
   568 	}
       
   569 
       
   570 	startPoint.iX-=KIndentPerLevel/2;
       
   571 
       
   572 
       
   573 	iGc->SetPenStyle(CGraphicsContext::ESolidPen);
       
   574 	iGc->SetPenColor(0);
       
   575 	if (itemLevel)
       
   576 		{
       
   577 		const TPoint horizLineStart=startPoint+TPoint(0,iItemHeight/2);
       
   578 		iGc->MoveTo(horizLineStart);
       
   579 		iGc->DrawLineTo(TPoint(horizLineStart.iX+(KIndentPerLevel*(aParagraphLevel-parentLevel))+KIndentPerLevel/2,horizLineStart.iY));
       
   580 		}
       
   581 
       
   582 
       
   583 	TInt lineIndentLevel=itemLevel;
       
   584 	TInt count=-1;
       
   585 
       
   586 
       
   587 
       
   588 	while (lineIndentLevel--)
       
   589 		{
       
   590 		count++;
       
   591 		
       
   592 		if (lineIndentLevel+1<itemLevel)
       
   593 			{
       
   594 			parent=itemToBeDrawn->Parent();
       
   595 			if (count>1)
       
   596 				{
       
   597 				TInt parentsToFind=count-1;
       
   598 				while (parentsToFind--)
       
   599 					parent=parent->Parent();
       
   600 				}
       
   601 			if (!(parent->HasFurtherSibling()))
       
   602 				{
       
   603 				parentLevel = GetParagraphLevel(parent);
       
   604 				startPoint=ItemPos(aItemIndex,parentLevel);	
       
   605 				startPoint.iX-=KIndentPerLevel/2;
       
   606 				continue;
       
   607 				}
       
   608 			else
       
   609 				{
       
   610 				if (parent->Parent()) parent=parent->Parent();
       
   611 				parentLevel = GetParagraphLevel(parent);
       
   612 				startPoint=ItemPos(aItemIndex,parentLevel);	
       
   613 				startPoint.iX-=KIndentPerLevel/2;
       
   614 				}
       
   615 			}
       
   616 
       
   617 
       
   618 
       
   619 		TInt vertLineLength=iItemHeight;
       
   620 		if (lineIndentLevel+1==itemLevel)
       
   621 			{
       
   622 			if (!itemToBeDrawn->HasFurtherSibling())
       
   623 				vertLineLength/=2;
       
   624 			}
       
   625 		iGc->MoveTo(startPoint);
       
   626 		iGc->DrawLineTo(TPoint(startPoint.iX,startPoint.iY+vertLineLength));
       
   627 		
       
   628 		startPoint.iX-=KIndentPerLevel;
       
   629 		}
       
   630 		
       
   631 	}
       
   632 
       
   633 
       
   634 
       
   635 
       
   636 
       
   637 // COutlineHListBoxModel
       
   638 ////////////////////////
       
   639 
       
   640 
       
   641 COutlineHListBoxModel* COutlineHListBoxModel::NewL(COutlineHListBox* aParent,CRichText* aText)
       
   642 {
       
   643 	COutlineHListBoxModel* self = new (ELeave) COutlineHListBoxModel;
       
   644 
       
   645 	CleanupStack::PushL(self);
       
   646 
       
   647 	self->iParent=aParent;
       
   648 	self->iText=aText;
       
   649 	self->ConstructL();
       
   650 
       
   651 	CleanupStack::Pop();
       
   652 	return self;
       
   653 }
       
   654 
       
   655 
       
   656 void COutlineHListBoxModel::ConstructL()
       
   657 {
       
   658 	 iOutlineTable = new (ELeave)COutlineTable(2);
       
   659 	 iOutlineMap=COutlineMap::NewL();
       
   660 
       
   661 	 // Construct the Outline table from the document
       
   662 	 CreateEntryTableL();
       
   663 
       
   664 }
       
   665 
       
   666 COutlineHListBoxModel::~COutlineHListBoxModel()
       
   667 	{
       
   668 	delete iOutlineMap;
       
   669 
       
   670 	delete iOutlineTable;
       
   671 
       
   672 	}
       
   673 
       
   674 
       
   675 TInt COutlineHListBoxModel::CurrentCharPosition()
       
   676 {
       
   677 	// This returns the character position in the document of the currently
       
   678 	// selected item in the listbox
       
   679 
       
   680 	// Get the current item's entry
       
   681 	TInt item = iParent->CurrentItemIndex();
       
   682 
       
   683 	CHierListItem* itemPtr=Item(item);
       
   684 	TInt paragraphIndex = iOutlineMap->Index(itemPtr);
       
   685 	
       
   686 	return (iOutlineTable->At(paragraphIndex).iParagraphPos);
       
   687 }
       
   688 
       
   689 
       
   690 void COutlineHListBoxModel::CreateEntryTableL()
       
   691 {
       
   692 	/* The scans through the document and creates the table which is then
       
   693 	   used by the outline control.
       
   694 	   Each entry in the table references one paragraph in the document that contains
       
   695 	   an outline level greater than zero. (Only styles have outline levels).
       
   696 	   For each of these paragraphs, the following information is stored:
       
   697 	   Paragraph no. in the document,
       
   698 		Character position of start of paragraph, length of paragraph (or a maximum of
       
   699 		128 - used to generate the text of each node in the control),
       
   700 		the outline level of the paragraph.
       
   701 	   Two boolean values are also stored:
       
   702 		isChild is True if the entry is the first child of a previous entry
       
   703 		lastEntry is True if this entry is the last entry at the current outline level
       
   704 		These two values are used to decide the structure of the tree
       
   705 	*/
       
   706 
       
   707 	   
       
   708 
       
   709 	TInt paragraphPos=0;
       
   710 	TInt paragraphLength=0;
       
   711 	TInt outlineLevel=0;
       
   712 	TInt lastOutlineLevel = 0;
       
   713 	TBool isChild=EFalse;
       
   714 //	TBool lastEntry=ETrue;
       
   715 	TBool styleChanges=EFalse;
       
   716 
       
   717 	TInt entryCount = 0;
       
   718 
       
   719 	TInt paragraphCount = iText->ParagraphCount();
       
   720 
       
   721 	TInt count;
       
   722 	TInt whileCount;
       
   723 	TInt parentLevel;
       
   724 
       
   725 
       
   726  	const CParaFormatLayer* paragraphStyle;
       
   727 	//
       
   728 	CEikonEnv* eikonEnv=CEikonEnv::Static();
       
   729 
       
   730 	eikonEnv->BusyMsgL(R_WORD_OUTLINE, KWaitingTime);
       
   731 
       
   732 	for (count=0; count<paragraphCount; count++)
       
   733 	{
       
   734 		// Get position of this paragraph
       
   735 		paragraphPos = iText->CharPosOfParagraph(paragraphLength, count);
       
   736 		if (paragraphLength>KMaxParagraphLength) paragraphLength=KMaxParagraphLength;
       
   737 
       
   738 		// Discard paragraphs with no text (length will be 1 because of paragraph delimiter)
       
   739 		if (paragraphLength>1) 
       
   740 		{
       
   741 		paragraphStyle=iText->ParagraphStyle(styleChanges, paragraphPos, paragraphLength-1);
       
   742 		if (paragraphStyle->SenseBase())
       
   743 		{
       
   744  		 outlineLevel=((CParagraphStyle*)paragraphStyle)->OutlineLevel();
       
   745 		 if (outlineLevel>0) 
       
   746 		 {
       
   747 			isChild = (lastOutlineLevel < outlineLevel && lastOutlineLevel>0);
       
   748 
       
   749 			iOutlineTable->AppendL(TOutlineEntry(count,outlineLevel,paragraphLength-1,paragraphPos,isChild,EFalse));	
       
   750 			entryCount++;
       
   751 			lastOutlineLevel=outlineLevel;
       
   752 		 }
       
   753 		}
       
   754 
       
   755 		}
       
   756 
       
   757 	}
       
   758 
       
   759 
       
   760 	// Now look through to find the final nodes at each level
       
   761 
       
   762 	if (entryCount) 
       
   763 	{
       
   764 		TInt childCount;
       
   765 
       
   766 		for (count=1; count<entryCount-1; count++)
       
   767 		{
       
   768 			lastOutlineLevel = iOutlineTable->At(count).iOutlineLevel;
       
   769 			
       
   770 			// Get parent level
       
   771 			whileCount = count;
       
   772 			childCount = 0;
       
   773 			while (whileCount>0)
       
   774 			{	
       
   775 				if (iOutlineTable->At(whileCount).iIsChild) childCount++;
       
   776 				if (iOutlineTable->At(whileCount).iLastEntry) childCount--;
       
   777 				if (childCount == 1) break;
       
   778 				whileCount--;
       
   779 			}
       
   780 			// Check if this node is at the top level already
       
   781 			if (whileCount==0) continue;
       
   782 			else parentLevel = iOutlineTable->At(whileCount-1).iOutlineLevel;
       
   783 
       
   784 			whileCount = count+1;
       
   785 
       
   786 			while (whileCount<entryCount)
       
   787 			{
       
   788 				outlineLevel = iOutlineTable->At(whileCount).iOutlineLevel;
       
   789 				if (outlineLevel <= lastOutlineLevel && outlineLevel>parentLevel) break;
       
   790 				if (outlineLevel <= parentLevel) 
       
   791 				{
       
   792 					iOutlineTable->At(count).iLastEntry = ETrue;
       
   793 					break;
       
   794 				}
       
   795 				whileCount++;
       
   796 			}
       
   797 		}
       
   798 
       
   799 		iOutlineTable->At(entryCount-1).iLastEntry = ETrue;
       
   800 
       
   801 
       
   802 	}
       
   803 	else 
       
   804 		{
       
   805 		eikonEnv->BusyMsgCancel();
       
   806 		User::Leave(KErrNoOutline);
       
   807 		}
       
   808 
       
   809 	eikonEnv->BusyMsgCancel();
       
   810 
       
   811 }
       
   812 
       
   813 void COutlineHListBoxModel::ScanHeading(TDes& aText)
       
   814 	{
       
   815 	// Scan the heading
       
   816 	for (TInt pos=0; pos < aText.Length(); pos++)
       
   817 		// Replace this charater with a normal space
       
   818 		if (aText[pos] == CEditableText::ENonBreakingSpace)
       
   819 			aText[pos] = ' ';
       
   820 	}
       
   821 
       
   822 void COutlineHListBoxModel::CreateRootListL()
       
   823 {
       
   824 	// This creates entries in the list box for all entries in the outline
       
   825 	// table which are not children of any other nodes 
       
   826 
       
   827 	iHierListArray=new(ELeave)CArrayFixSeg<CHierListItem*>(5);
       
   828 	CHierListItem* item;
       
   829 
       
   830 	TInt count;
       
   831 
       
   832 	TBuf<128> text;
       
   833 
       
   834 	TInt paragraphCount = iOutlineTable->Count();
       
   835 	TInt paragraphPos;
       
   836 	TInt paragraphLength;
       
   837 	TBool lastEntry;
       
   838 	TBool isChild;
       
   839 
       
   840 	TInt childCount = 0;
       
   841 
       
   842 	for (count=0; count<paragraphCount; count++)
       
   843 	{
       
   844 		paragraphPos= iOutlineTable->At(count).iParagraphPos;
       
   845 		paragraphLength= iOutlineTable->At(count).iParagraphLength;
       
   846 		lastEntry= iOutlineTable->At(count).iLastEntry;
       
   847 		isChild= iOutlineTable->At(count).iIsChild;
       
   848 
       
   849 		if (isChild) childCount++;
       
   850 
       
   851 		if (!isChild && childCount < 1)
       
   852 		{
       
   853 				iText->Extract(text, paragraphPos, paragraphLength);
       
   854 				// Scan th heading
       
   855 				ScanHeading(text);
       
   856 				item = new(ELeave)CHierListItem((TInt16)0);
       
   857 				CleanupStack::PushL(item);
       
   858 				item->SetTextL(text);
       
   859 	
       
   860 				AddItemL(item, -1, -1);
       
   861 				iOutlineMap->BindL(count, item);
       
   862 				CleanupStack::Pop(); // Pop item
       
   863 		}
       
   864 		if (lastEntry) childCount--;
       
   865 
       
   866 	}
       
   867 
       
   868 }
       
   869 
       
   870 
       
   871 void COutlineHListBoxModel::ExpandItemL(TInt aItemIndex)
       
   872 {
       
   873 	// This creates nodes for all immediate children of the given index
       
   874 
       
   875 	CHierListItem* itemToBeExpanded=Item(aItemIndex);
       
   876 	if (itemToBeExpanded->IsExpanded())
       
   877 		return;
       
   878 
       
   879 	TInt newItemIndex = aItemIndex;
       
   880 
       
   881 	TInt index;
       
   882 	TInt count;
       
   883 	TBuf<128> text;
       
   884 
       
   885 	TInt paragraphCount = iOutlineTable->Count();
       
   886 	TInt paragraphPos;
       
   887 	TInt paragraphLength;
       
   888 	TBool lastEntry;
       
   889 	TBool isChild;
       
   890 	TInt childCount = 0;
       
   891 	CHierListItem* item;
       
   892 
       
   893 	index = iOutlineMap->Index(itemToBeExpanded);
       
   894 
       
   895 
       
   896 	if (index != KErrNotFound)
       
   897 	{
       
   898 			for (count=index+1; count<paragraphCount; count++)
       
   899 			{
       
   900 				lastEntry= iOutlineTable->At(count).iLastEntry;
       
   901 				isChild= iOutlineTable->At(count).iIsChild;
       
   902 
       
   903 
       
   904 				if (isChild) childCount++;
       
   905 
       
   906 				if (childCount == 1)
       
   907 				{
       
   908 						paragraphPos= iOutlineTable->At(count).iParagraphPos;
       
   909 						paragraphLength= iOutlineTable->At(count).iParagraphLength;
       
   910 
       
   911 						iText->Extract(text, paragraphPos, paragraphLength);
       
   912 						ScanHeading(text);
       
   913 						item = new(ELeave)CHierListItem((TInt16)0);
       
   914 						CleanupStack::PushL(item);
       
   915 						item->SetTextL(text);
       
   916 
       
   917 						AddItemL(item, aItemIndex, newItemIndex++);
       
   918 
       
   919 						iOutlineMap->BindL(count, item);
       
   920 						CleanupStack::Pop(); // pop item
       
   921 						itemToBeExpanded->SetExpanded();	
       
   922 				}
       
   923 				if (lastEntry) childCount--;	
       
   924 				if (childCount == 0) break;
       
   925 			}
       
   926 	}
       
   927 }
       
   928 
       
   929 
       
   930 
       
   931 TInt COutlineHListBoxModel::GetItemByParagraph(TInt aPara)
       
   932 {
       
   933 	// Given a paragraph number in the Outline Table, this returns
       
   934 	// the item number in the list box.
       
   935 	
       
   936 		CHierListItem* thisPtr = iOutlineMap->Ptr(aPara);
       
   937 		TInt size = HierListArray()->Count();
       
   938 		TInt count;
       
   939 		TInt item = -1;
       
   940 
       
   941 		for (count=0; count<size; count++)
       
   942 		{
       
   943 			if (HierListArray()->At(count) == thisPtr) 
       
   944 			{
       
   945 				item = count;
       
   946 				break;
       
   947 			}
       
   948 		}
       
   949 		return item;
       
   950 }
       
   951 
       
   952 
       
   953 TInt COutlineHListBoxModel::ExpandCurrentPositionL(TInt aCursorPos)
       
   954 {
       
   955 	// This finds out which paragraph the cursor is currently at
       
   956 	// then expands its parents
       
   957 
       
   958 	TInt paragraphNo = iText->ParagraphNumberForPos(aCursorPos);
       
   959 	TInt count=0;
       
   960 	TInt stylePara = -1;
       
   961 	TInt paragraphCount = iOutlineTable->Count();
       
   962 
       
   963 	// Find out which style entry is above this position
       
   964 
       
   965 	for (count=0; count<paragraphCount; count++)
       
   966 	{
       
   967 		if (iOutlineTable->At(count).iParagraphNo > paragraphNo) break;
       
   968 		stylePara = count;
       
   969 	}
       
   970 
       
   971 
       
   972 	return (ExpandParagraphL(stylePara));
       
   973 
       
   974 }
       
   975 
       
   976 TInt COutlineHListBoxModel::ExpandParagraphL(TInt aPara)
       
   977 {
       
   978 	// This looks to see if the paragraphs parent node is expand, and if not,
       
   979 	// expand it by recursion.
       
   980 	// The maximum iteration level is the number of levels deep the initial node is,
       
   981 	// and is unlikely to be more than 2 or 3 levels.
       
   982 	// The theoretical maximum is 99 levels, (as the UI only support entry of level 0-99)
       
   983 
       
   984 
       
   985 	// Check that this paragraph has not been expanded
       
   986 
       
   987 	if (iOutlineMap->IndexPresent(aPara) || aPara == -1) return GetItemByParagraph(aPara);
       
   988 
       
   989 	// If this node is a first child, then try to open the previous node
       
   990 	// since it must be it's parent
       
   991 
       
   992 	if (iOutlineTable->At(aPara).iIsChild)
       
   993 	{
       
   994 		ExpandParagraphL(aPara-1); 
       
   995 		// Node aPara-1 is now guaranteed to exist, so open it up
       
   996 		TInt item = GetItemByParagraph(aPara-1);
       
   997 
       
   998 		if (item != -1) ExpandItemL(item);
       
   999 
       
  1000 		return GetItemByParagraph(aPara);
       
  1001 	}
       
  1002 		
       
  1003 
       
  1004 	// Need to look a bit further up since this node has siblings
       
  1005 
       
  1006 	TInt childCount = 0;
       
  1007 	TInt para = aPara - 1;
       
  1008 	TBool child;
       
  1009 
       
  1010 	while (aPara >= 0)
       
  1011 	{
       
  1012 		if (iOutlineTable->At(para).iLastEntry) childCount++;
       
  1013 		child = iOutlineTable->At(para).iIsChild;
       
  1014 
       
  1015 		if (child && childCount == 0)
       
  1016 		{
       
  1017 			// para is a child of the same level, so open its parent
       
  1018 			ExpandParagraphL(para-1); 
       
  1019 			TInt item = GetItemByParagraph(para-1);
       
  1020 			if (item != -1) ExpandItemL(item);
       
  1021 			return GetItemByParagraph(aPara);
       
  1022 		}
       
  1023 
       
  1024 		if (child) childCount--;
       
  1025 
       
  1026 		para--;
       
  1027 	}
       
  1028 
       
  1029 	return 0;
       
  1030 }
       
  1031 
       
  1032 
       
  1033 
       
  1034 
       
  1035