aknlayoutcompiler/src/MLEqCompData.cpp
changeset 0 f58d6ec98e88
child 1 b700e12870ca
equal deleted inserted replaced
-1:000000000000 0:f58d6ec98e88
       
     1 /*
       
     2 * Copyright (c) 2007 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 
       
    20 #include "MLEqCompData.h"
       
    21 #include "MLEqCompDataParse.h"
       
    22 #include "MLEqCompData2DHuiML.h"
       
    23 #include "MLAttributes.h"
       
    24 #include "FormulaTree.h"
       
    25 
       
    26 #include "LayoutCompilerErr.h"
       
    27 #include "CodeGenConsts.h"
       
    28 #include "UsefulDefinitions.h"
       
    29 
       
    30 #include "Akndef.hrh"
       
    31 
       
    32 #include <set>
       
    33 #include <sstream>
       
    34 #include <iostream>
       
    35 #include <algorithm>
       
    36 
       
    37 
       
    38 //
       
    39 // const data
       
    40 //
       
    41 
       
    42 
       
    43 
       
    44 const string KEqCompDataKeywordParamLeft = "l";
       
    45 const string KEqCompDataKeywordParamTop = "t";
       
    46 const string KEqCompDataKeywordParamRight = "r";
       
    47 const string KEqCompDataKeywordParamBottom = "b";
       
    48 const string KEqCompDataKeywordParamWidth = "w";
       
    49 const string KEqCompDataKeywordParamHeight = "h";
       
    50 
       
    51 const string KEqCompDataPaneOutputOrder[] = 
       
    52 	{
       
    53 	KEqCompDataKeywordParamLeft,
       
    54 	KEqCompDataKeywordParamTop,
       
    55 	KEqCompDataKeywordParamRight,
       
    56 	KEqCompDataKeywordParamBottom,
       
    57 	KEqCompDataKeywordParamWidth,
       
    58 	KEqCompDataKeywordParamHeight
       
    59 	};
       
    60 
       
    61 const int KEqCompDataPaneOutputOrderSize = ARRAY_LEN(KEqCompDataPaneOutputOrder);
       
    62 
       
    63 
       
    64 const string KEqCompDataKeywordParamType = "Type";
       
    65 const string KEqCompDataKeywordParamFont = "Font";
       
    66 const string KEqCompDataKeywordParamNumCols = "NumCols";
       
    67 const string KEqCompDataKeywordParamNumRows = "NumRows";
       
    68 const string KEqCompDataKeywordScreenContents = "Screen Contents";
       
    69 
       
    70 const string KEqCompDataKeywordUnderscore = "_";
       
    71 const string KEqCompDataKeywordLineNameSuffixGraphic = "g";
       
    72 const string KEqCompDataKeywordLineNameSuffixText = "t";
       
    73 
       
    74 const string KEqCompDataSearchCollectionNumeric = "0123456789";
       
    75 const string KEqCompDataBadValue = "Bad Value";
       
    76 const string KEqCompDataLayoutEmpty = "ELayoutEmpty";
       
    77 const string KEqCompDataUnknown = "unknown";
       
    78 
       
    79 const string KEqCompDataCellNameLeft("l");
       
    80 const string KEqCompDataCellNameRight("r");
       
    81 const string KEqCompDataCellNameJustification("J");
       
    82 
       
    83 const string KAttributeNameStyle1 = "style_1";
       
    84 const string KAttributeNameStyle1Plain = "plain";
       
    85 const string KAttributeNameStyle1Bold = "bold";
       
    86 
       
    87 const string KAttributeNameNumberOfColumns = "Number_of_columns";
       
    88 const string KAttributeNameNumberOfRows = "Number_of_rows";
       
    89 const string KAttributeNameNumberOfRowsColsAuto = "AUTO";
       
    90 
       
    91 //
       
    92 // struct TMLEqCompDataFormula
       
    93 //
       
    94 TMLEqCompDataFormula::TMLEqCompDataFormula()
       
    95 	:
       
    96 	iFormulaString(),
       
    97 	iZoomId(0),
       
    98 	iFormulaTree(NULL)
       
    99 	{
       
   100 
       
   101 	}
       
   102 
       
   103 TMLEqCompDataFormula::TMLEqCompDataFormula(const TMLEqCompDataFormula& aOther)
       
   104 	:
       
   105 	iFormulaString(aOther.iFormulaString),
       
   106 	iZoomId(aOther.iZoomId),
       
   107 	iFormulaTree(aOther.iFormulaTree)
       
   108 	{
       
   109 	int x = 0;
       
   110 	}
       
   111 
       
   112 const TMLEqCompDataFormula& TMLEqCompDataFormula::operator=(const TMLEqCompDataFormula& aOther)
       
   113 	{
       
   114 	if(this == &aOther)
       
   115 		return aOther;
       
   116 
       
   117 	iFormulaString = aOther.iFormulaString;
       
   118 	iZoomId = aOther.iZoomId;
       
   119 
       
   120 	if(iFormulaTree)
       
   121 		{
       
   122 		delete iFormulaTree;
       
   123 		iFormulaTree = 0;
       
   124 		}
       
   125 	iFormulaTree = aOther.iFormulaTree;
       
   126 	return *this;
       
   127 	}
       
   128 
       
   129 TMLEqCompDataFormula::TMLEqCompDataFormula(string aFormulaString)
       
   130 	:
       
   131 	iFormulaString(aFormulaString),
       
   132 	iZoomId(0),
       
   133 	iFormulaTree(NULL)
       
   134 	{
       
   135 
       
   136 	}
       
   137 
       
   138 TMLEqCompDataFormula::~TMLEqCompDataFormula()
       
   139 	{
       
   140 	delete iFormulaTree;
       
   141 	iFormulaTree = 0;
       
   142 	}
       
   143 
       
   144 
       
   145 bool TMLEqCompDataFormula::operator==(const TMLEqCompDataFormula& aOther) const
       
   146 	{
       
   147 	return (iFormulaString == aOther.iFormulaString && iZoomId == aOther.iZoomId);
       
   148 	}
       
   149 
       
   150 void TMLEqCompDataFormula::Compile()
       
   151 	{
       
   152 	if(!iFormulaTree)
       
   153 		{
       
   154 		iFormulaTree = FormulaTreeNode::Parse(iFormulaString);
       
   155 		}
       
   156 	else
       
   157 		{
       
   158 		throw GeneralErr(string("TMLEqCompDataFormula::Compile - formula already parsed."));
       
   159 		}
       
   160 	}
       
   161 
       
   162 //
       
   163 // TMLEqCompDataValuesOptionSet
       
   164 //
       
   165 void TMLEqCompDataValuesOptionSet::Compile()
       
   166 	{
       
   167 	for(iterator pFormula = begin(); pFormula != end(); ++pFormula)
       
   168 		{
       
   169 		pFormula->Compile();
       
   170 		}
       
   171 	}
       
   172 
       
   173 
       
   174 //
       
   175 // TMLEqCompDataValues
       
   176 //
       
   177 
       
   178 TMLEqCompDataValues::TMLEqCompDataValues()
       
   179 	: 
       
   180 	iLine(NULL), 
       
   181 	iName(KEqCompDataBadValue)
       
   182 	{
       
   183 	}
       
   184 
       
   185 TMLEqCompDataValues::TMLEqCompDataValues(TMLEqCompDataLine* aLine)
       
   186 	: 
       
   187 	iLine(aLine), 
       
   188 	iName(aLine->iName)
       
   189 	{
       
   190 	}
       
   191 
       
   192 bool TMLEqCompDataValues::operator==(const TMLEqCompDataValues& aOther) const
       
   193 	{
       
   194 	typedef const vector<TMLEqCompDataFormula> TBase;
       
   195 	bool eq =
       
   196 		iName == aOther.iName &&
       
   197 		(*static_cast<TBase*>(this) == aOther);
       
   198 	return eq;
       
   199 	}
       
   200 
       
   201 TMLEqCompDataValues::~TMLEqCompDataValues()
       
   202 	{
       
   203 	}
       
   204 
       
   205 bool TMLEqCompDataValues::Merge(TMLEqCompDataLine* aLine, string aName, TMLEqCompDataValues& aOtherValues, bool aMirrorMerge)
       
   206 	{
       
   207 /*
       
   208 	iLine = aLine;
       
   209 	iName = aName; // we may be swapping l and r
       
   210 
       
   211 	// create missing values in this line if needed
       
   212 	for (iterator pOtherVal=aOtherValues.begin(); pOtherVal!=aOtherValues.end(); ++pOtherVal)
       
   213 		{
       
   214 		TMLEqCompDataZoomLevels& otherZoomLevels = pOtherVal->second;
       
   215 		TMLEqCompDataZoomLevels& thisZoomLevels = (*this)[pOtherVal->first];
       
   216 		thisZoomLevels = otherZoomLevels; // we want exactly the correct number of calcs from the other cell
       
   217 		if(aMirrorMerge)
       
   218 			{
       
   219 			if(iName == KEqCompDataCellNameJustification)
       
   220 				{
       
   221 				// reverse the justification
       
   222 				for(TMLEqCompDataZoomLevels::iterator pCalcs = thisZoomLevels.begin(); pCalcs != thisZoomLevels.end(); ++pCalcs)
       
   223 					{
       
   224 					TMLEqCompDataCalcs& calcs = pCalcs->second;
       
   225 					for(TMLEqCompDataCalcs::iterator pVal = calcs.begin(); pVal != calcs.end(); ++pVal)
       
   226 						pVal->second = MirrorJustificationValue(pVal->second);
       
   227 					}
       
   228 				}
       
   229 			}
       
   230 		}
       
   231 */
       
   232 	return true;
       
   233 	}
       
   234 
       
   235 
       
   236 const string KParamLimitNames[] = { "NumCols", "NumRows" };
       
   237 const string KHorizNames[] = { "l", "r", "W" };
       
   238 const string KVertNames[] = { "t", "b", "H", "Font" };
       
   239 const set<string> KParamLimitNamesSet(KParamLimitNames, ARRAY_END(KParamLimitNames));
       
   240 const set<string> KHorizNamesSet(KHorizNames, ARRAY_END(KHorizNames));
       
   241 const set<string> KVertNamesSet(KVertNames, ARRAY_END(KVertNames));
       
   242 
       
   243 string TMLEqCompDataValues::MirrorJustificationValue(const string& aValue)
       
   244 	{
       
   245 	int val = CdlTkUtil::ParseInt(aValue);
       
   246 	if(val == ELayoutAlignLeft)
       
   247 		val = ELayoutAlignRight;
       
   248 	else if(val == ELayoutAlignRight)
       
   249 		val = ELayoutAlignLeft;
       
   250 	return CdlTkUtil::IntToString(val);
       
   251 	}
       
   252 
       
   253 
       
   254 void TMLEqCompDataValues::Compile(int aOptionSetId)
       
   255 	{
       
   256 	TMLEqCompDataValuesOptionSet& set = iOptionSets[aOptionSetId];
       
   257 	set.Compile();
       
   258 	}
       
   259 
       
   260 string TMLEqCompDataValues::CppValue(const string& aValue)
       
   261 	{
       
   262 	if (aValue.size())
       
   263 		return aValue;
       
   264 	else
       
   265 		return KEqCompDataLayoutEmpty;
       
   266 	}
       
   267 
       
   268 //
       
   269 // TMLEqCompDataParentInfoSelector
       
   270 //
       
   271 TMLEqCompDataParentInfoSelector::TMLEqCompDataParentInfoSelector()
       
   272 	{
       
   273 
       
   274 	}
       
   275 
       
   276 TMLEqCompDataParentInfoSelector::TMLEqCompDataParentInfoSelector(int aParentId, int aParentVariety)
       
   277 	:
       
   278 	iParentId(aParentId),
       
   279 	iParentVariety(aParentVariety)
       
   280 	{
       
   281 
       
   282 	}
       
   283 
       
   284 //
       
   285 //  TMLEqCompDataParentInfo
       
   286 //
       
   287 
       
   288 TMLEqCompDataParentInfo::TMLEqCompDataParentInfo()
       
   289 	:
       
   290 	iLine(0)
       
   291 	{
       
   292 
       
   293 	}
       
   294 
       
   295 TMLEqCompDataParentInfo::TMLEqCompDataParentInfo(TMLEqCompDataLine* aLine)
       
   296 	:
       
   297 	iLine(aLine)
       
   298 	{
       
   299 
       
   300 	}
       
   301 
       
   302 TMLEqCompDataParentInfo::~TMLEqCompDataParentInfo()
       
   303 	{
       
   304 
       
   305 	}
       
   306 
       
   307 void TMLEqCompDataParentInfo::Merge(const TMLEqCompDataParentInfo& aOther)
       
   308 	{
       
   309 /*
       
   310 	for (const_iterator pOtherVariety = aOther.begin(); pOtherVariety != aOther.end(); ++pOtherVariety)
       
   311 		{
       
   312 		int varietyIndex = pOtherVariety->first;
       
   313 		const TMLEqCompDataParentInfoSelector& selector = pOtherVariety->second;
       
   314 		insert(make_pair(varietyIndex, selector));
       
   315 		}
       
   316 */
       
   317 	}
       
   318 
       
   319 //
       
   320 //  TMLEqCompDataLine
       
   321 //
       
   322 
       
   323 TMLEqCompDataLine::TMLEqCompDataLine()
       
   324 :	iId(0),
       
   325 	iIsUnique(true), 
       
   326 	iIsMirroredHorizontally(false),
       
   327 	iType(EUnknownComponent),
       
   328 	iName(KEqCompDataUnknown),
       
   329 	iDrawingOrder(-1),
       
   330 	iParentTable(0),
       
   331 	iParentInfo(0),
       
   332 //	iAttributeInfo(0),
       
   333 	iNumCols(1),
       
   334 	iNumRows(1),
       
   335 	iGlobalIndex(0)
       
   336 	{	
       
   337 		
       
   338 	}
       
   339 
       
   340 TMLEqCompDataLine::TMLEqCompDataLine(const TMLEqCompDataLine& aOther)
       
   341 	{
       
   342 	if(this == &aOther)
       
   343 		return;
       
   344 
       
   345 /*
       
   346 	*this = aOther; // this will take a copy of the owning pointer
       
   347 	if(aOther.iParentInfo) // if it wasn't zero
       
   348 		iParentInfo = new TMLEqCompDataParentInfo(*(aOther.iParentInfo)); // we don't want to take ownership, so make our own copy
       
   349 	if(aOther.iAttributeInfo) // if it wasn't zero
       
   350 		iAttributeInfo = new TMLEqCompDataAttributeInfo(*(aOther.iAttributeInfo)); // we don't want to take ownership, so make our own copy
       
   351 */
       
   352 	for (iterator pVal = begin(); pVal != end(); ++pVal)
       
   353 		{
       
   354 		TMLEqCompDataValues& val = pVal->second;
       
   355 		val.iLine = this;
       
   356 		}
       
   357 	iParentTable = 0; // will be set during compile
       
   358 	}
       
   359 
       
   360 bool TMLEqCompDataLine::operator==(const TMLEqCompDataLine& aOther) const
       
   361 	{
       
   362 	return (Name() == aOther.Name()) && ValuesEqual(aOther);
       
   363 	}
       
   364 
       
   365 TMLEqCompDataLine::~TMLEqCompDataLine()
       
   366 	{
       
   367 /*
       
   368 	delete iParentInfo;
       
   369 	delete iAttributeInfo;
       
   370 */
       
   371 	}
       
   372 
       
   373 bool TMLEqCompDataLine::lessthan(TMLEqCompDataLine* aLeft, TMLEqCompDataLine* aRight)
       
   374 	{
       
   375 	string pureNameLeft = aLeft->NameDiscountingSuffix();
       
   376 	string pureNameRight = aRight->NameDiscountingSuffix();
       
   377 	if(pureNameLeft != pureNameRight)
       
   378 		{
       
   379 		return (aLeft->iName) < (aRight->iName);
       
   380 		}
       
   381 	else
       
   382 		{
       
   383 		int left = CdlTkUtil::ParseInt(aLeft->NameSuffix());
       
   384 		int right = CdlTkUtil::ParseInt(aRight->NameSuffix());
       
   385 		return left < right;
       
   386 		}
       
   387 	}
       
   388 
       
   389 bool TMLEqCompDataLine::ValuesEqual(const TMLEqCompDataLine& aOther) const
       
   390 	{
       
   391 	bool eq = true;
       
   392 	const_iterator pVal, pOther;
       
   393 	for (pVal = begin(), pOther = aOther.begin(); 
       
   394 		 eq && pVal != end() && pOther != aOther.end(); 
       
   395 		 ++pVal, ++pOther)
       
   396 		{
       
   397 		eq = (*pVal == *pOther);
       
   398 		}
       
   399 	eq = eq && pVal == end() && pOther == aOther.end();
       
   400 	return eq;
       
   401 	}
       
   402 
       
   403 string TMLEqCompDataLine::Name() const
       
   404 	{
       
   405 	return iName;
       
   406 	}
       
   407 
       
   408 bool TMLEqCompDataLine::Merge(TMLEqCompDataLine& aOtherLine)
       
   409 	{
       
   410 /*
       
   411 	bool compatible = 
       
   412 		(iId == aOtherLine.iId) ||
       
   413 		(iName == aOtherLine.iName) ||
       
   414 		(iType == aOtherLine.iType);
       
   415 	if(compatible)
       
   416 		{
       
   417 		iDrawingOrder = aOtherLine.iDrawingOrder;
       
   418 		iMaxVariety = aOtherLine.iMaxVariety;
       
   419 		iIsMirroredHorizontally |= aOtherLine.iIsMirroredHorizontally; // in the case of an elaf layout merging onto an abrw layout, the chirality will be preserved
       
   420 		iNeedsOptions |= aOtherLine.iNeedsOptions;
       
   421 
       
   422 		if(!iParentInfo)
       
   423 			{
       
   424 			// must be screen...
       
   425 			iParentInfo = new TMLEqCompDataParentInfo();
       
   426 			}
       
   427 		if(aOtherLine.iParentInfo)
       
   428 			{
       
   429 			iParentInfo->Merge(*(aOtherLine.iParentInfo));
       
   430 			}
       
   431 
       
   432 		if(!iAttributeInfo)
       
   433 			{
       
   434 			// must be screen...
       
   435 			iAttributeInfo = new TMLEqCompDataAttributeInfo();
       
   436 			}
       
   437 		if(aOtherLine.iAttributeInfo)
       
   438 			{
       
   439 			iAttributeInfo->Merge(*(aOtherLine.iAttributeInfo));
       
   440 			}
       
   441 
       
   442 		// for the API, we need to know if there are any multi-value components in either orientation
       
   443 		iNeedsCols = iNeedsCols || aOtherLine.iNeedsCols;
       
   444 		iNeedsRows = iNeedsRows || aOtherLine.iNeedsRows;
       
   445 		// however, we want exactly the correct number of calcs from the other cell
       
   446 		iNumCols = aOtherLine.iNumCols;
       
   447 		iNumRows = aOtherLine.iNumRows;
       
   448 
       
   449 		// if this line has no values, then we must do a mirror merge
       
   450 		bool mirrorMerge = empty() && iIsMirroredHorizontally;
       
   451 
       
   452 		// create missing values in this line if needed
       
   453 		for (TMLEqCompDataLine::iterator pOtherValues=aOtherLine.begin(); pOtherValues!=aOtherLine.end(); ++pOtherValues)
       
   454 			{
       
   455 			string index = pOtherValues->first;
       
   456 			if(mirrorMerge)
       
   457 				{
       
   458 				// flip left and right
       
   459 				if(index == KEqCompDataCellNameLeft)
       
   460 					index = KEqCompDataCellNameRight;
       
   461 				else if(index == KEqCompDataCellNameRight)
       
   462 					index = KEqCompDataCellNameLeft;
       
   463 				}
       
   464 
       
   465 			(*this)[index].Merge(this, index, pOtherValues->second, mirrorMerge);
       
   466 			}
       
   467 		}
       
   468 	return compatible;
       
   469 	*/
       
   470 	return false;
       
   471 	}
       
   472 
       
   473 TMLAttributeZoomLevels* TMLEqCompDataLine::GetAttributeZoomLevels(string aAttribName, int aVariety)
       
   474 	{
       
   475 /*
       
   476 	TMLAttributeZoomLevels* found = 0;
       
   477 	TMLEqCompData& data = *(iParentTable->iTables);
       
   478 	TMLAttributes& attributes = *(data.iAttributes);
       
   479 	int attribId = attributes.iNames[aAttribName];
       
   480 	if(attribId == 0)
       
   481 		throw GeneralErr(string("Attribute name not found: ") + aAttribName);
       
   482 	// find out from attribute info which attribute set we need
       
   483 	// but if there is none specified, we don't need to search
       
   484 	if(iAttributeInfo)
       
   485 		{
       
   486 		TMLEqCompDataAttributeInfoSelector& selector = (*iAttributeInfo)[aVariety];
       
   487 		// go to parent straight away, as parent always stores attribute data for its children
       
   488 		found = GetParentAttributeZoomLevels(selector.iAttributeSetName, attribId, aVariety);
       
   489 		}
       
   490 	return found;
       
   491 */
       
   492 	return NULL;
       
   493 	}
       
   494 
       
   495 TMLAttributeZoomLevels* TMLEqCompDataLine::GetParentAttributeZoomLevels(string aAttribSetName, int aAttribId, int aVariety)
       
   496 	{
       
   497 	TMLAttributeZoomLevels* found = NULL;
       
   498 	TMLEqCompDataParentInfo::iterator pFoundSelector = iParentInfo->find(aVariety);
       
   499 	if(pFoundSelector != iParentInfo->end())
       
   500 		{
       
   501 		const TMLEqCompDataParentInfoSelector& parentInfoSelector = pFoundSelector->second;
       
   502 		if(iParentTable && iParentTable->iParentLine)
       
   503 			{
       
   504 			found = iParentTable->iParentLine->FindAttributeZoomLevels(aAttribSetName, aAttribId);
       
   505 			if(!found)
       
   506 				{
       
   507 				// recurse to next parent container
       
   508 				int variety = parentInfoSelector.iParentVariety;
       
   509 				iParentTable->iParentLine->GetParentAttributeZoomLevels(aAttribSetName, aAttribId, variety);
       
   510 				}
       
   511 			}
       
   512 		}
       
   513 	return found;
       
   514 	}
       
   515 
       
   516 TMLAttributeZoomLevels* TMLEqCompDataLine::FindAttributeZoomLevels(string aAttribSetName, int aAttribId)
       
   517 	{
       
   518 	TMLEqCompData& data = *(iParentTable->iTables);
       
   519 	TMLAttributes& attributes = *(data.iAttributes);
       
   520 	int id = iId;
       
   521 	TMLAttributes::iterator foundAttributeSetComponent = attributes.find(id);
       
   522 	if(foundAttributeSetComponent != attributes.end())
       
   523 		{
       
   524 		TMLAttributeSetComponent& component = foundAttributeSetComponent->second;
       
   525 		TMLAttributeSet* pSet = component[aAttribSetName];
       
   526 		if(pSet)
       
   527 			{
       
   528 			TMLAttributeSet& attributeSet = *pSet;
       
   529 			TMLAttributeSet::iterator foundAttrib = attributeSet.find(aAttribId);
       
   530 			if(foundAttrib != attributeSet.end())
       
   531 				{
       
   532 				return &(foundAttrib->second);
       
   533 				}
       
   534 			}
       
   535 		}
       
   536 	return NULL;
       
   537 	}
       
   538 
       
   539 void TMLEqCompDataLine::Compile(int aOptionSetId)
       
   540 	{
       
   541 	// compile values
       
   542 	for(iterator pVal = begin(); pVal != end(); ++pVal)
       
   543 		{
       
   544 		(pVal->second).Compile(aOptionSetId);
       
   545 		}
       
   546 	}
       
   547 
       
   548 bool TMLEqCompDataLine::MatchNameDiscountingSuffix(const TMLEqCompDataLine& aLine) const
       
   549 	{
       
   550 	// we are trying to compare whether the names are the same apart from a trailing number
       
   551 	string pureName = NameDiscountingSuffix();
       
   552 	string pureNameOther = aLine.NameDiscountingSuffix();
       
   553 	string ending = pureName.substr(pureName.find_last_not_of(KEqCompDataKeywordUnderscore));
       
   554 
       
   555 	bool namesMatch = (pureName == pureNameOther);
       
   556 	bool correctEnding = (ending == KEqCompDataKeywordLineNameSuffixGraphic || ending == KEqCompDataKeywordLineNameSuffixText);
       
   557 	return (namesMatch && correctEnding);
       
   558 	}
       
   559 
       
   560 bool TMLEqCompDataLine::MatchType(const TMLEqCompDataLine& aLine) const
       
   561 	{
       
   562 	// first check that the type is equivalent
       
   563 	bool equivalent = false;
       
   564 	switch(iType)
       
   565 		{
       
   566 		case ETextComponent:
       
   567 			{
       
   568 			if(aLine.iType == ETextComponent)
       
   569 				{
       
   570 				equivalent = true;
       
   571 				}
       
   572 			break;
       
   573 			}
       
   574 		case EScreenComponent:
       
   575 		case EContainerComponent:
       
   576 		case EPaneComponent:
       
   577 		case EGraphicComponent:
       
   578 			{
       
   579 			if(aLine.iType == EScreenComponent
       
   580 				|| aLine.iType == EContainerComponent
       
   581 				|| aLine.iType == EPaneComponent
       
   582 				|| aLine.iType == EGraphicComponent)
       
   583 				{
       
   584 				equivalent = true;
       
   585 				}
       
   586 			break;
       
   587 			}
       
   588 		case EUnknownComponent:
       
   589 		default:
       
   590 			{
       
   591 			if(aLine.iType == EUnknownComponent)
       
   592 				{
       
   593 				equivalent = true;
       
   594 				}
       
   595 			break;
       
   596 			}
       
   597 		}
       
   598 
       
   599 	return equivalent;
       
   600 	}
       
   601 
       
   602 string TMLEqCompDataLine::NameDiscountingSuffix() const
       
   603 	{
       
   604 	int lastNonNumericPos = iName.find_last_not_of(KEqCompDataSearchCollectionNumeric);
       
   605 	int length = lastNonNumericPos + 1;
       
   606 	return iName.substr(0, length);
       
   607 	}
       
   608 
       
   609 string TMLEqCompDataLine::NameSuffix() const
       
   610 	{
       
   611 	int lastNonNumericPos = iName.find_last_not_of(KEqCompDataSearchCollectionNumeric);
       
   612 	int suffixPos = lastNonNumericPos + 1;
       
   613 	return iName.substr(suffixPos);
       
   614 	}
       
   615 
       
   616 int TMLEqCompDataLine::NumCols() const
       
   617 	{
       
   618 	return iNumCols;
       
   619 	}
       
   620 
       
   621 int TMLEqCompDataLine::NumRows() const
       
   622 	{
       
   623 	return iNumRows;
       
   624 	}
       
   625 
       
   626 
       
   627 void TMLEqCompDataLine::SetNumCols(int aNumCols)
       
   628 	{
       
   629 	iNumCols = aNumCols;
       
   630 	}
       
   631 
       
   632 void TMLEqCompDataLine::SetNumRows(int aNumRows)
       
   633 	{
       
   634 	iNumRows = aNumRows;
       
   635 	}
       
   636 
       
   637 
       
   638 //
       
   639 // TMLEqCompDataAttributeInfoSelector
       
   640 //
       
   641 TMLEqCompDataAttributeInfoSelector::TMLEqCompDataAttributeInfoSelector()
       
   642 	{
       
   643 
       
   644 	}
       
   645 
       
   646 TMLEqCompDataAttributeInfoSelector::TMLEqCompDataAttributeInfoSelector(string aAttributeSetName)
       
   647 	:
       
   648 	iAttributeSetName(aAttributeSetName)
       
   649 	{
       
   650 
       
   651 	}
       
   652 
       
   653 //
       
   654 //  TMLEqCompDataAttributeInfo
       
   655 //
       
   656 
       
   657 TMLEqCompDataAttributeInfo::TMLEqCompDataAttributeInfo()
       
   658 	:
       
   659 	iLine(0)
       
   660 	{
       
   661 
       
   662 	}
       
   663 
       
   664 TMLEqCompDataAttributeInfo::TMLEqCompDataAttributeInfo(TMLEqCompDataLine* aLine)
       
   665 	:
       
   666 	iLine(aLine)
       
   667 	{
       
   668 
       
   669 	}
       
   670 
       
   671 TMLEqCompDataAttributeInfo::~TMLEqCompDataAttributeInfo()
       
   672 	{
       
   673 
       
   674 	}
       
   675 
       
   676 void TMLEqCompDataAttributeInfo::Merge(const TMLEqCompDataAttributeInfo& aOther)
       
   677 	{
       
   678 	for (const_iterator pOtherVariety = aOther.begin(); pOtherVariety != aOther.end(); ++pOtherVariety)
       
   679 		{
       
   680 		int varietyIndex = pOtherVariety->first;
       
   681 		const TMLEqCompDataAttributeInfoSelector& selector = pOtherVariety->second;
       
   682 		insert(make_pair(varietyIndex, selector));
       
   683 		}
       
   684 	}
       
   685 
       
   686 
       
   687 //
       
   688 // TMLEqCompDataTableOptionSet
       
   689 //
       
   690 TMLEqCompDataTableOptionSet::TMLEqCompDataTableOptionSet()
       
   691 	:
       
   692 	iOrientation(EMLEqCompDataOptionSetOrientationUndefined)
       
   693 	{
       
   694 	
       
   695 	}
       
   696 
       
   697 TMLEqCompDataTableOptionSet::TMLEqCompDataTableOptionSet(const TMLEqCompDataTableOptionSet& aOther)
       
   698 	:
       
   699 	iOrientation(aOther.iOrientation)
       
   700 	{
       
   701 	for(const_iterator pOtherLines = aOther.begin(); pOtherLines != aOther.end(); ++pOtherLines)
       
   702 		{
       
   703 		push_back(*pOtherLines);
       
   704 		}
       
   705 	}
       
   706 
       
   707 TMLEqCompDataTableOptionSet::~TMLEqCompDataTableOptionSet()
       
   708 	{
       
   709 	// don't delete pointers to lines, as they are not owned
       
   710 	clear();
       
   711 	}
       
   712 
       
   713 void TMLEqCompDataTableOptionSet::Compile(int aOptionSetId)
       
   714 	{
       
   715 	for (iterator pLine = begin(); pLine != end(); ++pLine)
       
   716 		{
       
   717 		(*pLine)->Compile(aOptionSetId);
       
   718 		}
       
   719 	}
       
   720 
       
   721 TMLEqCompDataLine* TMLEqCompDataTableOptionSet::FindLine(int aId) const
       
   722 	{
       
   723 	for(const_iterator pLine = begin(); pLine != end(); ++pLine)
       
   724 		{
       
   725 		TMLEqCompDataLine* line = *pLine;
       
   726 		if(line)
       
   727 			{
       
   728 			if(line->iId == aId)
       
   729 				return line;
       
   730 			}
       
   731 		}
       
   732 	return NULL;
       
   733 	}
       
   734 
       
   735 //
       
   736 // TMLEqCompDataTable
       
   737 //
       
   738 
       
   739 TMLEqCompDataTable::TMLEqCompDataTable(TMLEqCompData* aTables)
       
   740 	: 
       
   741 	iTables(aTables), 
       
   742 	iParentLine(NULL), 
       
   743 	iId(0)
       
   744 	{
       
   745 	}
       
   746 
       
   747 TMLEqCompDataTable::TMLEqCompDataTable(TMLEqCompData* aTables, const TMLEqCompDataTable& aOther)
       
   748 	: 
       
   749 	iTables(aTables), 
       
   750 	iParentLine(NULL), 
       
   751 	iParentName(aOther.iParentName),
       
   752   	iId(aOther.iId)
       
   753 	{
       
   754 	for (const_iterator pOptionSet = aOther.begin(); pOptionSet != aOther.end(); ++pOptionSet)
       
   755 		{
       
   756 		insert(make_pair(pOptionSet->first, TMLEqCompDataTableOptionSet(pOptionSet->second)));
       
   757 		}
       
   758 	}
       
   759 
       
   760 TMLEqCompDataTable::~TMLEqCompDataTable()
       
   761 	{
       
   762 	// no need to delete lines, as they are not owned.
       
   763 	}
       
   764 
       
   765 string TMLEqCompDataTable::Name()
       
   766 	{
       
   767 	return iName;
       
   768 	}
       
   769 
       
   770 // @todo this will need to be modified to allow for searching for a line at a specific option set number
       
   771 TMLEqCompDataLine* TMLEqCompDataTable::FindLine(const string& aName)
       
   772 	{
       
   773 /*
       
   774 	for (iterator pLine = begin(); pLine != end(); ++pLine)
       
   775 		{
       
   776 		TMLEqCompDataLine& line = **pLine;
       
   777 		if (line.Name() == aName)
       
   778 			return *pLine;
       
   779 		}
       
   780 */
       
   781 	return 0;
       
   782 	}
       
   783 
       
   784 void TMLEqCompDataTable::Merge(TMLEqCompDataTable& aOther)
       
   785 	{
       
   786 /*
       
   787 	for (iterator pOtherLine = aOther.begin(); pOtherLine != aOther.end(); )
       
   788 		{
       
   789         TMLEqCompDataLine* found = FindLine((*pOtherLine)->Name());
       
   790         if(found)
       
   791             {
       
   792             found->Merge(**pOtherLine);
       
   793             delete *pOtherLine;
       
   794 			pOtherLine = aOther.erase(pOtherLine);
       
   795 			}
       
   796 		else
       
   797             {
       
   798 			push_back(*pOtherLine);
       
   799 			(*pOtherLine)->iParentTable = this;
       
   800 			pOtherLine = aOther.erase(pOtherLine);
       
   801 			}
       
   802 		}
       
   803 */
       
   804 	}
       
   805 
       
   806 
       
   807 void TMLEqCompDataTable::Compile()
       
   808 	{
       
   809 //	SetDefaultColumnNames();
       
   810 //	sort(begin(), end(), TMLEqCompDataLine::lessthan);	
       
   811 
       
   812 	for (iterator pOptionSet = begin(); pOptionSet != end(); ++pOptionSet)
       
   813 		{
       
   814 		pOptionSet->second.Compile(pOptionSet->first);
       
   815 		}
       
   816 	}
       
   817 
       
   818 
       
   819 
       
   820 const string KValueNames[] = { "Font", "C", "l", "r", "W", "J", "t", "r", "b", "H" };
       
   821 const set<string> KValueNamesSet(KValueNames, ARRAY_END(KValueNames));
       
   822 
       
   823 bool TMLEqCompDataTable::IsValueColumn(string aName)
       
   824 	{
       
   825 	return KValueNamesSet.find(aName) != KValueNamesSet.end();
       
   826 	}
       
   827 
       
   828 const string KNumericNames[] = { "C", "l", "r", "W", "t", "r", "b", "H" };
       
   829 const set<string> KNumericNamesSet(KNumericNames, ARRAY_END(KNumericNames));
       
   830 
       
   831 bool TMLEqCompDataTable::IsNumericColumn(string aName)
       
   832 	{
       
   833 	return KNumericNamesSet.find(aName) != KNumericNamesSet.end();
       
   834 	}
       
   835 
       
   836 const string KHorizontalColumnNames[] = { "l", "r", "W"};
       
   837 const set<string> KHorizontalNamesSet(KHorizontalColumnNames, ARRAY_END(KHorizontalColumnNames));
       
   838 
       
   839 bool TMLEqCompDataTable::IsHorizontalColumn(string aName)
       
   840 	{
       
   841 	return KHorizontalNamesSet.find(aName) != KHorizontalNamesSet.end();
       
   842 	}
       
   843 
       
   844 const string KVerticalColumnNames[] = {"t", "b", "H" };
       
   845 const set<string> KVerticalNamesSet(KVerticalColumnNames, ARRAY_END(KVerticalColumnNames));
       
   846 
       
   847 bool TMLEqCompDataTable::IsVerticalColumn(string aName)
       
   848 	{
       
   849 	return KVerticalNamesSet.find(aName) != KVerticalNamesSet.end();
       
   850 	}
       
   851 
       
   852 
       
   853 const string KPaneColumnNames[] = {"Item", "C", "l", "t", "r", "b", "W", "H", "Remarks"};
       
   854 const string KGraphicColumnNames[] = {"Item", "C", "l", "t", "r", "b", "W", "H", "Remarks"};
       
   855 const string KTextColumnNames[] = {"Font", "C", "l", "r", "t", "b", "W", "H", "J", "Remarks"};
       
   856 
       
   857 void TMLEqCompDataTable::SetDefaultColumnNames()
       
   858 	{
       
   859 	iColumnNames.clear();
       
   860 	iColumnNames.insert(iColumnNames.end(), KPaneColumnNames, ARRAY_END(KTextColumnNames)); // superset
       
   861 	}
       
   862 
       
   863 
       
   864 // 
       
   865 // TMLEqListComponent
       
   866 //
       
   867 TMLEqListComponent::TMLEqListComponent()
       
   868 	: 
       
   869 	iId(-1),
       
   870 	iName("badName")
       
   871 	{
       
   872 
       
   873 	}
       
   874 
       
   875 //
       
   876 // struct TMLEqParChildComponent
       
   877 //
       
   878 	TMLEqParChildComponent::TMLEqParChildComponent()
       
   879 	:
       
   880 	iId(-1),
       
   881 	iParentId(0)
       
   882 	{
       
   883 
       
   884 	}
       
   885 
       
   886 
       
   887 //
       
   888 // TMLEqCompData
       
   889 //
       
   890 
       
   891 TMLEqCompData::TMLEqCompData()
       
   892 	: 
       
   893 	iCanBeMirror(false),
       
   894 	iIsBaseInstance(false),
       
   895 	iAttributes(0)
       
   896 	{
       
   897 	}
       
   898 
       
   899 TMLEqCompData::TMLEqCompData(const TMLEqCompData& aOther)
       
   900 	{
       
   901 	*this = aOther;
       
   902 	}
       
   903 
       
   904 TMLEqCompData& TMLEqCompData::operator=(const TMLEqCompData& aOther)
       
   905 	{
       
   906 	if (this != &aOther)
       
   907 		{
       
   908 		iName = aOther.iName;
       
   909 		iCanBeMirror = aOther.iCanBeMirror;
       
   910 		for (const_iterator pTab = aOther.begin(); pTab != aOther.end(); ++pTab)
       
   911 			push_back(new TMLEqCompDataTable(this, **pTab));
       
   912 		Compile();
       
   913 		}
       
   914 	return *this;
       
   915 	}
       
   916 
       
   917 TMLEqCompData::~TMLEqCompData()
       
   918 	{
       
   919 	for (iterator pTab = begin(); pTab != end(); ++pTab)
       
   920 		delete *pTab;
       
   921 	DeleteComponents();
       
   922 	delete iAttributes;
       
   923 	}
       
   924 
       
   925 TMLEqCompDataLine* TMLEqCompData::FindComponent(const string& aName) const
       
   926 	{
       
   927 	for (TMLEqCompDataComponents::const_iterator pComp = iComponents.begin(); pComp != iComponents.end(); ++pComp)
       
   928 		{
       
   929 		TMLEqCompDataLine* line = pComp->second;
       
   930 		if (line->Name() == aName)
       
   931 			return line;
       
   932 		}
       
   933 
       
   934 	return 0;
       
   935 	}
       
   936 
       
   937 TMLEqCompDataLine* TMLEqCompData::FindLine(const string& aName) const
       
   938 	{
       
   939 	for (const_iterator pTab = begin(); pTab != end(); ++pTab)
       
   940 		{
       
   941 		TMLEqCompDataLine* line = (*pTab)->FindLine(aName);
       
   942 		if (line)
       
   943 			return line;
       
   944 		}
       
   945 
       
   946 	return 0;
       
   947 	}
       
   948 
       
   949 TMLEqCompDataTable* TMLEqCompData::FindTable(const string& aName) const
       
   950 	{
       
   951 	for (const_iterator pTab = begin(); pTab != end(); ++pTab)
       
   952 		{
       
   953 		if ((*pTab)->Name() == aName)
       
   954 			return *pTab;
       
   955 		}
       
   956 
       
   957 	return 0;
       
   958 	}
       
   959 
       
   960 TMLEqCompDataTable* TMLEqCompData::FindTable(int aId) const
       
   961 	{
       
   962 	for (const_iterator pTab = begin(); pTab != end(); ++pTab)
       
   963 		{
       
   964 		if ((*pTab)->iId == aId)
       
   965 			return *pTab;
       
   966 		}
       
   967 
       
   968 	return 0;
       
   969 	}
       
   970 
       
   971 void TMLEqCompData::Merge(TMLEqCompData& aOther)
       
   972 	{
       
   973 	iName = aOther.iName;
       
   974 	iCanBeMirror |= aOther.iCanBeMirror; // in the case of an elaf layout merging onto an abrw layout, the chirality will be preserved
       
   975 	MergeComponents(aOther);
       
   976 	}
       
   977 
       
   978 void TMLEqCompData::MergeComponents(TMLEqCompData& aOther)
       
   979     {
       
   980 	for (TMLEqCompDataComponents::iterator pOtherLine = aOther.iComponents.begin(); pOtherLine != aOther.iComponents.end(); ++pOtherLine)
       
   981 		{
       
   982 		TMLEqCompDataLine& otherLine = *(pOtherLine->second);
       
   983         TMLEqCompDataLine* found = FindComponent(otherLine.iName);
       
   984         if(found)
       
   985 			{
       
   986 			found->Merge(otherLine);
       
   987 			}
       
   988 		else
       
   989 			{
       
   990 			TMLEqCompDataLine* newLine = new TMLEqCompDataLine(otherLine);
       
   991 			iComponents.insert(make_pair(otherLine.iId, newLine));
       
   992 			}
       
   993 		}
       
   994 	}
       
   995 
       
   996 void TMLEqCompData::Compile()
       
   997 	{
       
   998 	UpdateNames();
       
   999 	CreateTables();
       
  1000 
       
  1001 	// now add a special table for the screen contents
       
  1002 	TMLEqCompDataTable* topTab = new TMLEqCompDataTable(this);
       
  1003 	topTab->iId = -1;
       
  1004 	topTab->iName = KEqCompDataKeywordScreenContents;
       
  1005 
       
  1006 	// then insert each line into its parent
       
  1007 	for (TMLEqCompDataComponents::iterator pComp = iComponents.begin(); pComp != iComponents.end(); ++pComp)
       
  1008 		{
       
  1009 		TMLEqCompDataLine& line = *(pComp->second);
       
  1010 		if(line.iType == TMLEqCompDataLine::EScreenComponent)
       
  1011 			{
       
  1012 			line.iParentTable = topTab;
       
  1013 			TMLEqCompDataTableOptionSet& optionSet = (*topTab)[0];
       
  1014 			optionSet.push_back(&line);
       
  1015 			}
       
  1016 		else
       
  1017 			{
       
  1018 			bool parentFound = false;
       
  1019 			TMLEqParChildComponent* parChild = iParChildComponents[line.iId];
       
  1020 			int parentId = parChild->iParentId;
       
  1021 			if(parentId != 0)
       
  1022 				{
       
  1023 				TMLEqCompDataTable* parentTable = FindTable(parentId);
       
  1024 				TMLEqCompDataLine* parentLine = iComponents[parentId];
       
  1025 				if(parentTable)
       
  1026 					{
       
  1027 					line.iParentTable = parentTable;
       
  1028 
       
  1029 					// iterate through the line and populate the table option sets as needed
       
  1030 					for(TMLEqCompDataLine::iterator pValues = line.begin(); pValues != line.end(); ++pValues)
       
  1031 						{
       
  1032 						TMLEqCompDataValues& values = pValues->second;
       
  1033 						TMLEqCompDataValuesOptionSets& sets = values.iOptionSets;
       
  1034 						for(TMLEqCompDataValuesOptionSets::iterator pValuesOptionSet = sets.begin(); pValuesOptionSet != sets.end(); ++pValuesOptionSet)
       
  1035 							{
       
  1036 							TMLEqCompDataValuesOptionSet& valuesSet = pValuesOptionSet->second;
       
  1037 							int optionId = pValuesOptionSet->first;
       
  1038 							TMLEqCompDataTableOptionSet& tableSet = (*parentTable)[optionId]; // constructs if not yet present
       
  1039 							if(tableSet.iOrientation != valuesSet.iOrientation)
       
  1040 								tableSet.iOrientation = valuesSet.iOrientation;
       
  1041 							
       
  1042 							TMLEqCompDataLine* lineInTable = tableSet.FindLine(line.iId);
       
  1043 							if(!lineInTable)
       
  1044 								{
       
  1045 								// make one
       
  1046 								tableSet.push_back(&line);
       
  1047 								}
       
  1048 							}
       
  1049 						}
       
  1050 
       
  1051 					// copy the pointer from the components table
       
  1052 //					parentTable->insert(make_pair(line.iId, &line));
       
  1053 					parentFound = true;
       
  1054 
       
  1055 					// now insert the table into its place in the tree
       
  1056 					parentTable->iParentLine = iComponents[parentId];
       
  1057 					}
       
  1058 				else
       
  1059 					{
       
  1060 					parentFound = false;
       
  1061 					}
       
  1062 				}
       
  1063 			if(!parentFound)
       
  1064 				{
       
  1065                 string errorText = string(" TMLEqCompData::Compile() - can't find parent component: ");
       
  1066 				errorText += CdlTkUtil::IntToString(parentId);
       
  1067 				throw GeneralErr(errorText);
       
  1068 				}
       
  1069 			}		
       
  1070 		}	
       
  1071 	push_back(topTab);
       
  1072 	
       
  1073 	// now compile the tables
       
  1074 	iterator pTab;
       
  1075 	for (pTab = begin(); pTab != end(); ++pTab)
       
  1076 		(*pTab)->Compile();
       
  1077 
       
  1078 	// now sort the tables
       
  1079 //	sort(begin(), end(), TMLEqCompDataTable::lessthan);	
       
  1080 	}
       
  1081 
       
  1082 void TMLEqCompData::UpdateNames()
       
  1083 	{
       
  1084 	// from the list of components, get the name of each line from the list
       
  1085 	for (TMLEqCompDataComponents::iterator pComp = iComponents.begin(); pComp != iComponents.end(); ++pComp)
       
  1086 		{
       
  1087 		TMLEqCompDataLine* line = pComp->second;
       
  1088 		TMLEqListComponent* pListComp = iListComponents[line->iId];
       
  1089 		line->iName = pListComp->iName;
       
  1090 		}
       
  1091 
       
  1092 	}
       
  1093 
       
  1094 void TMLEqCompData::CreateTables()
       
  1095 	{
       
  1096 	// from the list of components, first create a table for each pane
       
  1097 	for (TMLEqCompDataComponents::iterator pComp = iComponents.begin(); pComp != iComponents.end(); ++pComp)
       
  1098 		{
       
  1099 		TMLEqCompDataLine& line = *(pComp->second);
       
  1100 		switch(line.iType)
       
  1101 			{
       
  1102 			case TMLEqCompDataLine::EScreenComponent:
       
  1103 			case TMLEqCompDataLine::EContainerComponent:
       
  1104 			case TMLEqCompDataLine::EPaneComponent:
       
  1105 				{
       
  1106 				TMLEqCompDataTable* tab = new TMLEqCompDataTable(this);
       
  1107 				tab->iId = line.iId;
       
  1108 				tab->iName = line.iName;
       
  1109 				push_back(tab);
       
  1110 				break;
       
  1111 				}
       
  1112 			case TMLEqCompDataLine::EGraphicComponent:
       
  1113 			case TMLEqCompDataLine::ETextComponent:
       
  1114 				{
       
  1115 				// text and graphic components are not panes 
       
  1116 				// and are therefore not represented in our internal object model as tables
       
  1117 				break;
       
  1118 				}
       
  1119 			default:
       
  1120 				{
       
  1121 				cout << "TMLEqCompData::CreateTables() - uncategorised component\n";
       
  1122 				break;
       
  1123 				}
       
  1124 			}	
       
  1125 		}
       
  1126 	}
       
  1127 
       
  1128 void TMLEqCompData::DeleteComponents()
       
  1129 	{
       
  1130 	for (TMLEqCompDataComponents::iterator pComp = iComponents.begin(); pComp != iComponents.end(); ++pComp)
       
  1131 		delete pComp->second;
       
  1132 	}
       
  1133 
       
  1134 // End of File