os/textandloc/textrendering/word/SRC/WPOUTLNE.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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