--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/aknlayoutcompiler/src/MLCompData.cpp Thu Dec 17 09:14:18 2009 +0200
@@ -0,0 +1,1312 @@
+/*
+* Copyright (c) 2002-2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*
+*/
+
+
+#include "MLCompData.h"
+#include "MLCompDataParse.h"
+#include "MLCompData2Cdl.h"
+#include "MLAttributes.h"
+
+#include "LayoutCompilerErr.h"
+#include "CodeGenConsts.h"
+#include "UsefulDefinitions.h"
+
+#include "Akndef.hrh"
+
+#include <set>
+#include <sstream>
+#include <iostream>
+#include <algorithm>
+
+
+//
+// const data
+//
+
+const string KCompDataPaneOutputOrder[] = {"C", "l", "t", "r", "b", "W", "H"};
+const string KCompDataPaneOutputOrderMirrored[] = {"C", "r", "t", "l", "b", "W", "H"};
+const int KCompDataPaneOutputOrderSize = ARRAY_LEN(KCompDataPaneOutputOrder);
+
+const string KCompDataGraphicOutputOrder[] = {"NumCols", "NumRows", "C", "l", "t", "r", "b", "W", "H"};
+const string KCompDataGraphicOutputOrderMirrored[] = {"NumCols", "NumRows", "C", "r", "t", "l", "b", "W", "H"};
+const int KCompDataGraphicOutputOrderSize = ARRAY_LEN(KCompDataGraphicOutputOrder);
+
+const string KCompDataTextOutputOrder[] = {"NumCols", "NumRows", "C", "l", "t", "r", "b", "W", "H", "J", "Font"};
+const string KCompDataTextOutputOrderMirrored[] = {"NumCols", "NumRows", "C", "r", "t", "l", "b", "W", "H", "J", "Font"};
+const int KCompDataTextOutputOrderSize = ARRAY_LEN(KCompDataTextOutputOrder);
+
+const string KCompDataKeywordParamHeight = "H";
+const string KCompDataKeywordParamType = "Type";
+const string KCompDataKeywordParamFont = "Font";
+const string KCompDataKeywordParamNumCols = "NumCols";
+const string KCompDataKeywordParamNumRows = "NumRows";
+const string KCompDataKeywordScreenContents = "Screen Contents";
+
+const string KCompDataKeywordUnderscore = "_";
+const string KCompDataKeywordLineNameSuffixGraphic = "g";
+const string KCompDataKeywordLineNameSuffixText = "t";
+
+const string KCompDataSearchCollectionNumeric = "0123456789";
+const string KCompDataBadValue = "Bad Value";
+const string KCompDataLayoutEmpty = "ELayoutEmpty";
+const string KCompDataUnknown = "unknown";
+
+const string KCompDataCellNameLeft("l");
+const string KCompDataCellNameRight("r");
+const string KCompDataCellNameJustification("J");
+
+const string KAttributeNameStyle1 = "style_1";
+const string KAttributeNameStyle2 = "style_2";
+const string KAttributeNameStyle3 = "style_3";
+const string KAttributeNameStyle1Plain = "plain";
+const string KAttributeNameStyle1Bold = "bold";
+const string KAttributeNameStyle3Outline = "outline";
+
+const string KAttributeNameNumberOfColumns = "Number_of_columns";
+const string KAttributeNameNumberOfRows = "Number_of_rows";
+const string KAttributeNameNumberOfRowsColsAuto = "AUTO";
+
+
+//
+// TMLCompDataValues
+//
+
+TMLCompDataValues::TMLCompDataValues()
+ :
+ iLine(NULL),
+ iName(KCompDataBadValue)
+ {
+ }
+
+TMLCompDataValues::TMLCompDataValues(TMLCompDataLine* aLine)
+ :
+ iLine(aLine),
+ iName(aLine->iName)
+ {
+ }
+
+bool TMLCompDataValues::operator==(const TMLCompDataValues& aOther) const
+ {
+ typedef const map<int, TMLCompDataZoomLevels> TBase;
+ bool eq =
+ iName == aOther.iName &&
+ (*static_cast<TBase*>(this) == aOther);
+ return eq;
+ }
+
+TMLCompDataValues::~TMLCompDataValues()
+ {
+ }
+
+bool TMLCompDataValues::Merge(TMLCompDataLine* aLine, string aName, TMLCompDataValues& aOtherValues, bool aMirrorMerge)
+ {
+ iLine = aLine;
+ iName = aName; // we may be swapping l and r
+
+ // create missing values in this line if needed
+ for (iterator pOtherVal=aOtherValues.begin(); pOtherVal!=aOtherValues.end(); ++pOtherVal)
+ {
+ TMLCompDataZoomLevels& otherZoomLevels = pOtherVal->second;
+ TMLCompDataZoomLevels& thisZoomLevels = (*this)[pOtherVal->first];
+ thisZoomLevels = otherZoomLevels; // we want exactly the correct number of calcs from the other cell
+ if(aMirrorMerge)
+ {
+ if(iName == KCompDataCellNameJustification)
+ {
+ // reverse the justification
+ for(TMLCompDataZoomLevels::iterator pCalcs = thisZoomLevels.begin(); pCalcs != thisZoomLevels.end(); ++pCalcs)
+ {
+ TMLCompDataCalcs& calcs = pCalcs->second;
+ for(TMLCompDataCalcs::iterator pVal = calcs.begin(); pVal != calcs.end(); ++pVal)
+ pVal->second = MirrorJustificationValue(pVal->second);
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+const string KParamLimitNames[] = { "NumCols", "NumRows" };
+const string KHorizNames[] = { "l", "r", "W" };
+const string KVertNames[] = { "t", "b", "H", "Font" };
+const set<string> KParamLimitNamesSet(KParamLimitNames, ARRAY_END(KParamLimitNames));
+const set<string> KHorizNamesSet(KHorizNames, ARRAY_END(KHorizNames));
+const set<string> KVertNamesSet(KVertNames, ARRAY_END(KVertNames));
+
+TMLCompDataValues::TCompDataCellType TMLCompDataValues::Type(string aName)
+ {
+ TMLCompDataValues::TCompDataCellType type;
+ if(KParamLimitNamesSet.find(aName) != KParamLimitNamesSet.end())
+ {
+ type = TMLCompDataValues::ECellTypeParamLimit;
+ }
+ else if(KHorizNamesSet.find(aName) != KHorizNamesSet.end())
+ {
+ type = TMLCompDataValues::ECellTypeCol;
+ }
+ else if(KVertNamesSet.find(aName) != KVertNamesSet.end())
+ {
+ type = TMLCompDataValues::ECellTypeRow;
+ }
+ else
+ {
+ type = TMLCompDataValues::ECellTypeDefault;
+ }
+ return type;
+ }
+
+
+string TMLCompDataValues::MirrorJustificationValue(const string& aValue)
+ {
+ int val = CdlTkUtil::ParseInt(aValue);
+ if(val == ELayoutAlignLeft)
+ val = ELayoutAlignRight;
+ else if(val == ELayoutAlignRight)
+ val = ELayoutAlignLeft;
+ return CdlTkUtil::IntToString(val);
+ }
+
+
+void TMLCompDataValues::Compile(const string& aCellName)
+ {
+ // ensure that missing varieties are filled with null values
+ // we assume that each variety is present in all zoom levels that are defined
+ if(iLine) // screen contents isn't contained in a line
+ {
+ int thisSize = size();
+ int numVarieties = iLine->MaxVariety() + 1; // get zero based index
+ int maximum = max(numVarieties, thisSize);
+ int maxMulti;
+ switch(TMLCompDataValues::Type(aCellName))
+ {
+ case ECellTypeCol:
+ maxMulti = iLine->NumCols();
+ break;
+ case ECellTypeRow:
+ maxMulti = iLine->NumRows();
+ break;
+ default:
+ maxMulti = 1;
+ break;
+ }
+ for(int ii = 0; ii < maximum; ii++)
+ {
+ // operator[] fills in missing values
+ TMLCompDataZoomLevels& zoomLevels = (*this)[ii];
+ for(TMLCompDataZoomLevels::iterator pCalcs = zoomLevels.begin(); pCalcs != zoomLevels.end(); ++pCalcs)
+ {
+ TMLCompDataCalcs& calcs = pCalcs->second;
+ if(ii < numVarieties)
+ {
+ if(calcs.size() > maxMulti)
+ {
+ // Handle the case where data from a merged instance has too many calcs
+ TMLCompDataCalcs::iterator start = calcs.find(maxMulti);
+ TMLCompDataCalcs::iterator end = calcs.end();
+ calcs.erase(start, end);
+ }
+ }
+ else
+ {
+ // get rid of varieties from instances that we have merged onto
+ calcs.clear();
+ }
+ }
+ }
+ }
+ }
+
+string TMLCompDataValues::CppValue(const string& aValue)
+ {
+ if (aValue.size())
+ return aValue;
+ else
+ return KCompDataLayoutEmpty;
+ }
+
+//
+// TMLCompDataParentInfoSelector
+//
+TMLCompDataParentInfoSelector::TMLCompDataParentInfoSelector()
+ {
+
+ }
+
+TMLCompDataParentInfoSelector::TMLCompDataParentInfoSelector(int aParentId, int aParentVariety)
+ :
+ iParentId(aParentId),
+ iParentVariety(aParentVariety)
+ {
+
+ }
+
+//
+// TMLCompDataParentInfo
+//
+
+TMLCompDataParentInfo::TMLCompDataParentInfo()
+ :
+ iLine(0)
+ {
+
+ }
+
+TMLCompDataParentInfo::TMLCompDataParentInfo(TMLCompDataLine* aLine)
+ :
+ iLine(aLine)
+ {
+
+ }
+
+TMLCompDataParentInfo::~TMLCompDataParentInfo()
+ {
+
+ }
+
+void TMLCompDataParentInfo::Merge(const TMLCompDataParentInfo& aOther)
+ {
+ for (const_iterator pOtherVariety = aOther.begin(); pOtherVariety != aOther.end(); ++pOtherVariety)
+ {
+ int varietyIndex = pOtherVariety->first;
+ const TMLCompDataParentInfoSelector& selector = pOtherVariety->second;
+ insert(make_pair(varietyIndex, selector));
+ }
+ }
+
+//
+// TMLCompDataLine
+//
+
+TMLCompDataLine::TMLCompDataLine()
+: iId(0),
+ iIsUnique(true),
+ iIsMirroredHorizontally(false),
+ iType(EUnknownComponent),
+ iName(KCompDataUnknown),
+ iDrawingOrder(-1),
+ iMaxVariety(0),
+ iParentTable(0),
+ iParentInfo(0),
+ iAttributeInfo(0),
+ iNumCols(1),
+ iNumRows(1),
+ iNeedsOptions(false),
+ iNeedsCols(false),
+ iNeedsRows(false),
+ iGlobalIndex(0)
+ {
+
+ }
+
+TMLCompDataLine::TMLCompDataLine(const TMLCompDataLine& aOther)
+ {
+ if(this == &aOther)
+ return;
+ *this = aOther; // this will take a copy of the owning pointer
+ if(aOther.iParentInfo) // if it wasn't zero
+ iParentInfo = new TMLCompDataParentInfo(*(aOther.iParentInfo)); // we don't want to take ownership, so make our own copy
+ if(aOther.iAttributeInfo) // if it wasn't zero
+ iAttributeInfo = new TMLCompDataAttributeInfo(*(aOther.iAttributeInfo)); // we don't want to take ownership, so make our own copy
+
+ for (iterator pVal = begin(); pVal != end(); ++pVal)
+ {
+ TMLCompDataValues& val = pVal->second;
+ val.iLine = this;
+ }
+ iParentTable = 0; // will be set during compile
+ }
+
+bool TMLCompDataLine::operator==(const TMLCompDataLine& aOther) const
+ {
+ return (Name() == aOther.Name()) && ValuesEqual(aOther);
+ }
+
+TMLCompDataLine::~TMLCompDataLine()
+ {
+ delete iParentInfo;
+ delete iAttributeInfo;
+ }
+
+bool TMLCompDataLine::lessthan(TMLCompDataLine* aLeft, TMLCompDataLine* aRight)
+ {
+ string pureNameLeft = aLeft->NameDiscountingSuffix();
+ string pureNameRight = aRight->NameDiscountingSuffix();
+ if(pureNameLeft != pureNameRight)
+ {
+ return (aLeft->iName) < (aRight->iName);
+ }
+ else
+ {
+ int left = CdlTkUtil::ParseInt(aLeft->NameSuffix());
+ int right = CdlTkUtil::ParseInt(aRight->NameSuffix());
+ return left < right;
+ }
+ }
+
+bool TMLCompDataLine::ValuesEqual(const TMLCompDataLine& aOther) const
+ {
+ bool eq = true;
+ const_iterator pVal, pOther;
+ for (pVal = begin(), pOther = aOther.begin();
+ eq && pVal != end() && pOther != aOther.end();
+ ++pVal, ++pOther)
+ {
+ eq = (*pVal == *pOther);
+ }
+ eq = eq && pVal == end() && pOther == aOther.end();
+ return eq;
+ }
+
+string TMLCompDataLine::Name() const
+ {
+ return iName;
+ }
+
+bool TMLCompDataLine::Merge(TMLCompDataLine& aOtherLine)
+ {
+ bool compatible =
+ (iId == aOtherLine.iId) ||
+ (iName == aOtherLine.iName) ||
+ (iType == aOtherLine.iType);
+ if(compatible)
+ {
+ iDrawingOrder = aOtherLine.iDrawingOrder;
+ iMaxVariety = aOtherLine.iMaxVariety;
+ iIsMirroredHorizontally |= aOtherLine.iIsMirroredHorizontally; // in the case of an elaf layout merging onto an abrw layout, the chirality will be preserved
+ iNeedsOptions |= aOtherLine.iNeedsOptions;
+
+ if(!iParentInfo)
+ {
+ // must be screen...
+ iParentInfo = new TMLCompDataParentInfo();
+ }
+ if(aOtherLine.iParentInfo)
+ {
+ iParentInfo->Merge(*(aOtherLine.iParentInfo));
+ }
+
+ if(!iAttributeInfo)
+ {
+ // must be screen...
+ iAttributeInfo = new TMLCompDataAttributeInfo();
+ }
+ if(aOtherLine.iAttributeInfo)
+ {
+ iAttributeInfo->Merge(*(aOtherLine.iAttributeInfo));
+ }
+
+ // for the API, we need to know if there are any multi-value components in either orientation
+ iNeedsCols = iNeedsCols || aOtherLine.iNeedsCols;
+ iNeedsRows = iNeedsRows || aOtherLine.iNeedsRows;
+ // however, we want exactly the correct number of calcs from the other cell
+ iNumCols = aOtherLine.iNumCols;
+ iNumRows = aOtherLine.iNumRows;
+
+ // if this line has no values, then we must do a mirror merge
+ bool mirrorMerge = empty() && iIsMirroredHorizontally;
+
+ // create missing values in this line if needed
+ for (TMLCompDataLine::iterator pOtherValues=aOtherLine.begin(); pOtherValues!=aOtherLine.end(); ++pOtherValues)
+ {
+ string index = pOtherValues->first;
+ if(mirrorMerge)
+ {
+ // flip left and right
+ if(index == KCompDataCellNameLeft)
+ index = KCompDataCellNameRight;
+ else if(index == KCompDataCellNameRight)
+ index = KCompDataCellNameLeft;
+ }
+
+ (*this)[index].Merge(this, index, pOtherValues->second, mirrorMerge);
+ }
+ }
+ return compatible;
+ }
+
+TMLAttributeZoomLevels* TMLCompDataLine::GetAttributeZoomLevels(string aAttribName, int aVariety)
+ {
+ TMLAttributeZoomLevels* found = 0;
+ TMLCompData& data = *(iParentTable->iTables);
+ TMLAttributes& attributes = *(data.iAttributes);
+ int attribId = attributes.iNames[aAttribName];
+ if(attribId == 0)
+ throw GeneralErr(string("Attribute name not found: ") + aAttribName);
+ // find out from attribute info which attribute set we need
+ // but if there is none specified, we don't need to search
+ if(iAttributeInfo)
+ {
+ TMLCompDataAttributeInfoSelector& selector = (*iAttributeInfo)[aVariety];
+ // go to parent straight away, as parent always stores attribute data for its children
+ found = GetParentAttributeZoomLevels(selector.iAttributeSetName, attribId, aVariety);
+ }
+ return found;
+ }
+
+TMLAttributeZoomLevels* TMLCompDataLine::GetParentAttributeZoomLevels(string aAttribSetName, int aAttribId, int aVariety)
+ {
+ TMLAttributeZoomLevels* found = NULL;
+ TMLCompDataParentInfo::iterator pFoundSelector = iParentInfo->find(aVariety);
+ if(pFoundSelector != iParentInfo->end())
+ {
+ const TMLCompDataParentInfoSelector& parentInfoSelector = pFoundSelector->second;
+ if(iParentTable && iParentTable->iParentLine)
+ {
+ found = iParentTable->iParentLine->FindAttributeZoomLevels(aAttribSetName, aAttribId);
+ if(!found)
+ {
+ // recurse to next parent container
+ int variety = parentInfoSelector.iParentVariety;
+ iParentTable->iParentLine->GetParentAttributeZoomLevels(aAttribSetName, aAttribId, variety);
+ }
+ }
+ }
+ return found;
+ }
+
+TMLAttributeZoomLevels* TMLCompDataLine::FindAttributeZoomLevels(string aAttribSetName, int aAttribId)
+ {
+ TMLCompData& data = *(iParentTable->iTables);
+ TMLAttributes& attributes = *(data.iAttributes);
+ int id = iId;
+ TMLAttributes::iterator foundAttributeSetComponent = attributes.find(id);
+ if(foundAttributeSetComponent != attributes.end())
+ {
+ TMLAttributeSetComponent& component = foundAttributeSetComponent->second;
+ TMLAttributeSet* pSet = component[aAttribSetName];
+ if(pSet)
+ {
+ TMLAttributeSet& attributeSet = *pSet;
+ TMLAttributeSet::iterator foundAttrib = attributeSet.find(aAttribId);
+ if(foundAttrib != attributeSet.end())
+ {
+ return &(foundAttrib->second);
+ }
+ }
+ }
+ return NULL;
+ }
+
+void TMLCompDataLine::Compile()
+ {
+ // compile values
+ for(iterator pVal = begin(); pVal != end(); ++pVal)
+ {
+ (pVal->second).Compile(pVal->first);
+ }
+ CompileParamLimits(TMLCompDataValues::ECellTypeCol, KCompDataKeywordParamNumCols);
+ CompileParamLimits(TMLCompDataValues::ECellTypeRow, KCompDataKeywordParamNumRows);
+ CompileFontHeights();
+ }
+
+void TMLCompDataLine::CompileParamLimits(TMLCompDataValues::TCompDataCellType aParamLimitType, const string& aParamLimitCellName)
+ {
+ TMLCompDataValues paramLimits(this);
+
+ for(iterator pValues = begin(); pValues != end(); ++pValues)
+ {
+ string cellName = pValues->first;
+ if(TMLCompDataValues::Type(cellName) == aParamLimitType)
+ {
+ // calculate the param limits for this cell
+ TMLCompDataValues& values = pValues->second;
+ for(TMLCompDataValues::iterator pZoomLevels = values.begin(); pZoomLevels != values.end(); ++pZoomLevels)
+ {
+ int nextVariety = pZoomLevels->first;
+ TMLCompDataZoomLevels& zoomLevels = pZoomLevels->second;
+ TMLCompDataZoomLevels& paramLimitsZoomLevels = paramLimits[nextVariety];
+ for(TMLCompDataZoomLevels::iterator pCalcs = zoomLevels.begin(); pCalcs != zoomLevels.end(); ++pCalcs)
+ {
+ // accumulate the largest size of calc into the param limit
+ int zoomLevel = pCalcs->first;
+ int nextParamLimit = pCalcs->second.size();
+ TMLCompDataCalcs& paramLimitCalcs = paramLimitsZoomLevels[zoomLevel];
+ string& paramLimit = paramLimitCalcs[0];
+ int currentParamLimit = CdlTkUtil::ParseInt(paramLimit);
+ if(nextParamLimit > currentParamLimit)
+ paramLimit = CdlTkUtil::IntToString(nextParamLimit);
+ }
+ if(!paramLimitsZoomLevels.size())
+ {
+ // there were no defined values for this variety, but we know we'll
+ // insert an empty value at least
+ TMLCompDataCalcs& paramLimitCalcs = paramLimitsZoomLevels[EAknUiZoomNormal];
+ paramLimitCalcs.insert(make_pair(0, CdlTkUtil::IntToString(1)));
+ }
+ }
+ }
+ }
+ insert(make_pair(aParamLimitCellName, paramLimits));
+ }
+
+void TMLCompDataLine::CompileFontHeights()
+ {
+ if(iType == ETextComponent)
+ {
+ TMLCompDataValues font(this);
+
+ TMLCompDataValues types = (*this)[KCompDataKeywordParamType];
+ TMLCompDataValues heights = (*this)[KCompDataKeywordParamHeight];
+
+ // note that these are the number of varieties, there may be zoom level and then rows inside
+ int numTypeVarieties = types.size();
+ int numHeightVarieties = heights.size();
+
+ for(TMLCompDataValues::iterator pZoomLevels = heights.begin(); pZoomLevels != heights.end(); ++pZoomLevels)
+ {
+ int nextVariety = pZoomLevels->first;
+ TMLAttributeZoomLevels* style1ZoomLevels = GetAttributeZoomLevels(KAttributeNameStyle1, nextVariety);
+ TMLAttributeZoomLevels* style3ZoomLevels = GetAttributeZoomLevels(KAttributeNameStyle3, nextVariety);
+ TMLCompDataZoomLevels& heightsZoomLevels = pZoomLevels->second;
+ TMLCompDataZoomLevels& typesZoomLevels = types[nextVariety];
+ TMLCompDataZoomLevels& fontZoomLevels = font[nextVariety];
+
+ for(TMLCompDataZoomLevels::iterator pHeightCalcs = heightsZoomLevels.begin(); pHeightCalcs != heightsZoomLevels.end(); ++pHeightCalcs)
+ {
+ // if the types don't have zoom data, fall back to normal zoom
+ int zoomIndex = pHeightCalcs->first;
+ int numTypesZoomLevels = typesZoomLevels.size();
+ int typeZoomIndex = numTypesZoomLevels > 1 ? zoomIndex : EAknUiZoomNormal;
+ TMLCompDataCalcs& typeCalcs = typesZoomLevels[typeZoomIndex];
+
+ // get attribute data
+ int outline = 0;
+ int posture = 0;
+ int weight = 0;
+ if(style1ZoomLevels)
+ {
+ string style1 = (*style1ZoomLevels)[pHeightCalcs->first];
+ if(style1 == KAttributeNameStyle1Bold)
+ weight = 1;
+ }
+ if(style3ZoomLevels)
+ {
+ string style3 = (*style3ZoomLevels)[pHeightCalcs->first];
+ if(style3 == KAttributeNameStyle3Outline)
+ outline = 1;
+ }
+
+ // we want to have a font id for each height, even if the spec
+ // has not specified the type each time
+ TMLCompDataCalcs& fontCalcs = fontZoomLevels[pHeightCalcs->first];
+ TMLCompDataCalcs& next = pHeightCalcs->second;
+ for(TMLCompDataCalcs::iterator pHeightCalc = next.begin(); pHeightCalc != next.end(); ++pHeightCalc)
+ {
+ // for undefined type, let font provider use default,
+ // and always choose the first type for a multi value item
+ int calcIndex = pHeightCalc->first;
+ int type = numTypeVarieties > 0 ? CdlTkUtil::ParseInt(typeCalcs[0]) : ELayoutCompilerFontCategoryUndefined;
+ int height = numHeightVarieties > 0 ? CdlTkUtil::ParseInt(pHeightCalc->second) : 0;
+ int fontId = EncodeFontId(height, outline, posture, weight, type);
+ fontCalcs[calcIndex] = CdlTkUtil::IntToString(fontId);
+ }
+ }
+ }
+ insert(make_pair(string(KCompDataKeywordParamFont), font));
+ }
+ }
+
+int TMLCompDataLine::EncodeFontId(int aHeight, int aOutline, int aPosture, int aWeight, int aCategory) const
+ {
+ //
+ // 31 | 30 - 21 | 20 - 07 | 06 | 05 | 04 | 03 - 00
+ // encoded | text pane height 0-1023 | <not used> | outline | posture | weight | category
+
+ int encodedMasked = 1 << 31;
+ int heightMasked = aHeight << 21;
+
+ int outlineMasked = aOutline << 6;
+ int postureMasked = aPosture << 5;
+ int weightMasked = aWeight << 4;
+ int categoryMasked = aCategory;
+
+ return(encodedMasked | heightMasked | outlineMasked | postureMasked | weightMasked | categoryMasked);
+ }
+
+bool TMLCompDataLine::MatchParams(const TMLCompDataLine& aLine) const
+ {
+ if (NeedsOptions() != aLine.NeedsOptions())
+ return false;
+ if (NeedsCols() != aLine.NeedsCols())
+ return false;
+ if (NeedsRows() != aLine.NeedsRows())
+ return false;
+ return true;
+ }
+
+bool TMLCompDataLine::MatchNameDiscountingSuffix(const TMLCompDataLine& aLine) const
+ {
+ // we are trying to compare whether the names are the same apart from a trailing number
+ string pureName = NameDiscountingSuffix();
+ string pureNameOther = aLine.NameDiscountingSuffix();
+ string ending = pureName.substr(pureName.find_last_not_of(KCompDataKeywordUnderscore));
+
+ bool namesMatch = (pureName == pureNameOther);
+ bool correctEnding = (ending == KCompDataKeywordLineNameSuffixGraphic || ending == KCompDataKeywordLineNameSuffixText);
+ return (namesMatch && correctEnding);
+ }
+
+bool TMLCompDataLine::MatchType(const TMLCompDataLine& aLine) const
+ {
+ // first check that the type is equivalent
+ bool equivalent = false;
+ switch(iType)
+ {
+ case ETextComponent:
+ {
+ if(aLine.iType == ETextComponent)
+ {
+ equivalent = true;
+ }
+ break;
+ }
+ case EScreenComponent:
+ case EContainerComponent:
+ case EPaneComponent:
+ case EGraphicComponent:
+ {
+ if(aLine.iType == EScreenComponent
+ || aLine.iType == EContainerComponent
+ || aLine.iType == EPaneComponent
+ || aLine.iType == EGraphicComponent)
+ {
+ equivalent = true;
+ }
+ break;
+ }
+ case EUnknownComponent:
+ default:
+ {
+ if(aLine.iType == EUnknownComponent)
+ {
+ equivalent = true;
+ }
+ break;
+ }
+ }
+
+ return equivalent;
+ }
+
+string TMLCompDataLine::NameDiscountingSuffix() const
+ {
+ int lastNonNumericPos = iName.find_last_not_of(KCompDataSearchCollectionNumeric);
+ int length = lastNonNumericPos + 1;
+ return iName.substr(0, length);
+ }
+
+string TMLCompDataLine::NameSuffix() const
+ {
+ int lastNonNumericPos = iName.find_last_not_of(KCompDataSearchCollectionNumeric);
+ int suffixPos = lastNonNumericPos + 1;
+ return iName.substr(suffixPos);
+ }
+
+bool TMLCompDataLine::NeedsParams() const
+ {
+ return iNeedsOptions || iNeedsCols || iNeedsRows;
+ }
+
+bool TMLCompDataLine::NeedsOptions() const
+ {
+ return iNeedsOptions;
+ }
+
+bool TMLCompDataLine::NeedsCols() const
+ {
+ return iNeedsCols;
+ }
+
+bool TMLCompDataLine::NeedsRows() const
+ {
+ return iNeedsRows;
+ }
+
+int TMLCompDataLine::MaxVariety() const
+ {
+ return iMaxVariety;
+ }
+
+int TMLCompDataLine::NumCols() const
+ {
+ return iNumCols;
+ }
+
+int TMLCompDataLine::NumRows() const
+ {
+ return iNumRows;
+ }
+
+
+void TMLCompDataLine::SetMaxVariety(int aMaxVariety)
+ {
+ iMaxVariety = aMaxVariety;
+ if(iMaxVariety > 0) // zero based
+ iNeedsOptions = true;
+ }
+
+void TMLCompDataLine::SetNumCols(int aNumCols)
+ {
+ iNumCols = aNumCols;
+ if(iNumCols > 1)
+ iNeedsCols = true;
+ }
+
+void TMLCompDataLine::SetNumRows(int aNumRows)
+ {
+ iNumRows = aNumRows;
+ if(iNumRows > 1)
+ iNeedsRows = true;
+ }
+
+void TMLCompDataLine::SetNeedsCols(bool aNeeds)
+ {
+ iNeedsCols = aNeeds;
+ }
+
+void TMLCompDataLine::SetNeedsRows(bool aNeeds)
+ {
+ iNeedsRows = aNeeds;
+ }
+
+//
+// TMLCompDataAttributeInfoSelector
+//
+TMLCompDataAttributeInfoSelector::TMLCompDataAttributeInfoSelector()
+ {
+
+ }
+
+TMLCompDataAttributeInfoSelector::TMLCompDataAttributeInfoSelector(string aAttributeSetName)
+ :
+ iAttributeSetName(aAttributeSetName)
+ {
+
+ }
+
+//
+// TMLCompDataAttributeInfo
+//
+
+TMLCompDataAttributeInfo::TMLCompDataAttributeInfo()
+ :
+ iLine(0)
+ {
+
+ }
+
+TMLCompDataAttributeInfo::TMLCompDataAttributeInfo(TMLCompDataLine* aLine)
+ :
+ iLine(aLine)
+ {
+
+ }
+
+TMLCompDataAttributeInfo::~TMLCompDataAttributeInfo()
+ {
+
+ }
+
+void TMLCompDataAttributeInfo::Merge(const TMLCompDataAttributeInfo& aOther)
+ {
+ for (const_iterator pOtherVariety = aOther.begin(); pOtherVariety != aOther.end(); ++pOtherVariety)
+ {
+ int varietyIndex = pOtherVariety->first;
+ const TMLCompDataAttributeInfoSelector& selector = pOtherVariety->second;
+ insert(make_pair(varietyIndex, selector));
+ }
+ }
+
+
+
+//
+// TMLCompDataTable::TMLCompDataSubTable
+//
+
+bool TMLCompDataTable::TMLCompDataSubTable::NeedsParams() const
+ {
+ return iNeedsOption || iNeedsCol || iNeedsRow;
+ }
+
+
+//
+// TMLCompDataTable
+//
+
+TMLCompDataTable::TMLCompDataTable(TMLCompData* aTables)
+ :
+ iTables(aTables),
+ iParentLine(NULL),
+ iFirstLineGlobalIndex(-1),
+ iAppend(false),
+ iId(0),
+ iNeedsP(false),
+ iNeedsIndex(false)
+ {
+ }
+
+TMLCompDataTable::TMLCompDataTable(TMLCompData* aTables, const TMLCompDataTable& aOther)
+ :
+ iTables(aTables),
+ iParentLine(NULL),
+ iFirstLineGlobalIndex(aOther.iFirstLineGlobalIndex),
+ iAppend(aOther.iAppend), iColumnNames(aOther.iColumnNames), iName(aOther.iName),
+ iParentName(aOther.iParentName),
+ iId(aOther.iId)
+ {
+ for (const_iterator pLine = aOther.begin(); pLine != aOther.end(); ++pLine)
+ push_back(new TMLCompDataLine(**pLine));
+ }
+
+TMLCompDataTable::~TMLCompDataTable()
+ {
+ for (iterator pLine = begin(); pLine != end(); ++pLine)
+ delete *pLine;
+ }
+
+bool TMLCompDataTable::lessthan(TMLCompDataTable* aLeft, TMLCompDataTable* aRight)
+ {
+ return (aLeft->iId) < (aRight->iId);
+ }
+
+string TMLCompDataTable::Name()
+ {
+ return iName;
+ }
+
+TMLCompDataLine* TMLCompDataTable::FindLine(const string& aName)
+ {
+ for (iterator pLine = begin(); pLine != end(); ++pLine)
+ {
+ TMLCompDataLine& line = **pLine;
+ string paramLimitsName = MLCompDataToCdl::LineParamLimitsApiName(line);
+ // first check the lines for a direct match
+ // then try the param limits instead
+ if (line.Name() == aName ||
+ (line.NeedsParams() && paramLimitsName == aName))
+ return *pLine;
+ }
+ return 0;
+ }
+
+TMLCompDataTable::TMLCompDataSubTable* TMLCompDataTable::FindSubTable(const string& aName)
+ {
+ for(TMLCompDataSubTables::iterator pSub = iSubTables.begin(); pSub != iSubTables.end(); ++pSub)
+ {
+ TMLCompDataSubTable& sub = **pSub;
+ string subTableName = MLCompDataToCdl::SubTableApiName(sub);
+ string subTableLimitsName = MLCompDataToCdl::SubTableLimitsApiName(sub);
+ string paramLimitsName = MLCompDataToCdl::SubTableParamLimtsApiName(sub);
+ TMLCompDataLine& line = *((*this)[0]);
+ // first check the lines for a direct match
+ // then try the param limits instead
+ if (subTableName == aName ||
+ subTableLimitsName == aName ||
+ (sub.NeedsParams() && paramLimitsName == aName)) // need to check whether the subtable needs params
+ return ⊂
+ }
+ return 0;
+ }
+
+void TMLCompDataTable::Merge(TMLCompDataTable& aOther)
+ {
+ for (iterator pOtherLine = aOther.begin(); pOtherLine != aOther.end(); )
+ {
+ TMLCompDataLine* found = FindLine((*pOtherLine)->Name());
+ if(found)
+ {
+ found->Merge(**pOtherLine);
+ delete *pOtherLine;
+ pOtherLine = aOther.erase(pOtherLine);
+ }
+ else
+ {
+ push_back(*pOtherLine);
+ (*pOtherLine)->iParentTable = this;
+ pOtherLine = aOther.erase(pOtherLine);
+ }
+ }
+ }
+
+
+void TMLCompDataTable::Compile()
+ {
+ SetDefaultColumnNames();
+ sort(begin(), end(), TMLCompDataLine::lessthan);
+
+ iNeedsIndex = false;
+ iNeedsP = false;
+ for (iterator pLine = begin(); pLine != end(); ++pLine)
+ {
+ (*pLine)->Compile();
+ }
+ BuildSubTables();
+ NormalizeSubTables();
+ }
+
+void TMLCompDataTable::BuildSubTables()
+ {
+ DestroySubTables();
+
+ int count = size();
+ if(count > 0)
+ {
+ TMLCompDataSubTable* subTable = 0;
+ for (int i=0; i<count; i++)
+ {
+ TMLCompDataLine& line = *(*this)[i];
+ if (subTable)
+ {
+ TMLCompDataLine* firstLine = (*this)[(*subTable)[0]];
+ if (firstLine->NameSuffix() == "1" && firstLine->MatchNameDiscountingSuffix(line) && firstLine->MatchType(line))
+ {
+ subTable->iName = line.NameDiscountingSuffix();
+ }
+ else // only terminate the subtable if the lines don't match, or if the first line isn't numbered "1"
+ {
+ if (subTable->size() > 1)
+ iSubTables.push_back(subTable);
+ else
+ delete subTable;
+ subTable = new TMLCompDataSubTable;
+ }
+ }
+ else
+ {
+ subTable = new TMLCompDataSubTable;
+ }
+ subTable->iNeedsOption |= line.NeedsOptions();
+ subTable->iNeedsCol |= line.NeedsCols();
+ subTable->iNeedsRow |= line.NeedsRows();
+ subTable->push_back(i);
+ }
+
+ if (subTable->size() > 1)
+ {
+ iSubTables.push_back(subTable);
+ }
+ else
+ delete subTable;
+ }
+ }
+
+void TMLCompDataTable::NormalizeSubTables()
+ {
+ for(TMLCompDataSubTables::iterator pSub = iSubTables.begin(); pSub != iSubTables.end(); ++pSub)
+ {
+ TMLCompDataSubTable& sub = **pSub;
+ for(TMLCompDataSubTable::iterator pLineId = sub.begin(); pLineId != sub.end(); ++pLineId)
+ {
+ TMLCompDataLine& line = *((*this)[*pLineId]);
+
+ line.iNeedsOptions |= sub.iNeedsOption;
+ line.iNeedsCols |= sub.iNeedsCol;
+ line.iNeedsRows |= sub.iNeedsRow;
+ }
+ }
+ }
+
+
+void TMLCompDataTable::DestroySubTables()
+ {
+ for (TMLCompDataSubTables::iterator pSub = iSubTables.begin(); pSub != iSubTables.end(); ++pSub)
+ delete *pSub;
+ iSubTables.clear();
+ }
+
+
+const string KValueNames[] = { "Font", "C", "l", "r", "W", "J", "t", "r", "b", "H" };
+const set<string> KValueNamesSet(KValueNames, ARRAY_END(KValueNames));
+
+bool TMLCompDataTable::IsValueColumn(string aName)
+ {
+ return KValueNamesSet.find(aName) != KValueNamesSet.end();
+ }
+
+const string KNumericNames[] = { "C", "l", "r", "W", "t", "r", "b", "H" };
+const set<string> KNumericNamesSet(KNumericNames, ARRAY_END(KNumericNames));
+
+bool TMLCompDataTable::IsNumericColumn(string aName)
+ {
+ return KNumericNamesSet.find(aName) != KNumericNamesSet.end();
+ }
+
+const string KHorizontalColumnNames[] = { "l", "r", "W"};
+const set<string> KHorizontalNamesSet(KHorizontalColumnNames, ARRAY_END(KHorizontalColumnNames));
+
+bool TMLCompDataTable::IsHorizontalColumn(string aName)
+ {
+ return KHorizontalNamesSet.find(aName) != KHorizontalNamesSet.end();
+ }
+
+const string KVerticalColumnNames[] = {"t", "b", "H" };
+const set<string> KVerticalNamesSet(KVerticalColumnNames, ARRAY_END(KVerticalColumnNames));
+
+bool TMLCompDataTable::IsVerticalColumn(string aName)
+ {
+ return KVerticalNamesSet.find(aName) != KVerticalNamesSet.end();
+ }
+
+
+const string KPaneColumnNames[] = {"Item", "C", "l", "t", "r", "b", "W", "H", "Remarks"};
+const string KGraphicColumnNames[] = {"Item", "C", "l", "t", "r", "b", "W", "H", "Remarks"};
+const string KTextColumnNames[] = {"Font", "C", "l", "r", "t", "b", "W", "H", "J", "Remarks"};
+
+void TMLCompDataTable::SetDefaultColumnNames()
+ {
+ iColumnNames.clear();
+ iColumnNames.insert(iColumnNames.end(), KPaneColumnNames, ARRAY_END(KTextColumnNames)); // superset
+ }
+
+TMLCompDataTable::TMLCompDataSubTable::TMLCompDataSubTable()
+:
+ iNeedsOption(false),
+ iNeedsCol(false),
+ iNeedsRow(false)
+ {
+ }
+
+
+//
+// TMLCompData
+//
+
+TMLCompData::TMLCompData()
+ :
+ iCanBeMirror(false),
+ iIsBaseInstance(false),
+ iAttributes(0)
+ {
+ }
+
+TMLCompData::TMLCompData(const TMLCompData& aOther)
+ {
+ *this = aOther;
+ }
+
+TMLCompData& TMLCompData::operator=(const TMLCompData& aOther)
+ {
+ if (this != &aOther)
+ {
+ iName = aOther.iName;
+ iCanBeMirror = aOther.iCanBeMirror;
+ for (const_iterator pTab = aOther.begin(); pTab != aOther.end(); ++pTab)
+ push_back(new TMLCompDataTable(this, **pTab));
+ Compile();
+ }
+ return *this;
+ }
+
+TMLCompData::~TMLCompData()
+ {
+ for (iterator pTab = begin(); pTab != end(); ++pTab)
+ delete *pTab;
+ DeleteComponents();
+ delete iAttributes;
+ }
+
+TMLCompDataLine* TMLCompData::FindComponent(const string& aName) const
+ {
+ for (TMLComponents::const_iterator pComp = iComponents.begin(); pComp != iComponents.end(); ++pComp)
+ {
+ TMLCompDataLine* line = pComp->second;
+ if (line->Name() == aName)
+ return line;
+ }
+
+ return 0;
+ }
+
+TMLCompDataLine* TMLCompData::FindLine(const string& aName) const
+ {
+ for (const_iterator pTab = begin(); pTab != end(); ++pTab)
+ {
+ TMLCompDataLine* line = (*pTab)->FindLine(aName);
+ if (line)
+ return line;
+ }
+
+ return 0;
+ }
+
+TMLCompDataTable* TMLCompData::FindTable(const string& aName) const
+ {
+ for (const_iterator pTab = begin(); pTab != end(); ++pTab)
+ {
+ if ((*pTab)->Name() == aName)
+ return *pTab;
+ }
+
+ return 0;
+ }
+
+TMLCompDataTable* TMLCompData::FindTable(int aId) const
+ {
+ for (const_iterator pTab = begin(); pTab != end(); ++pTab)
+ {
+ if ((*pTab)->iId == aId)
+ return *pTab;
+ }
+
+ return 0;
+ }
+
+TMLCompDataTable::TMLCompDataSubTable* TMLCompData::FindSubTable(const string& aName) const
+ {
+ for (const_iterator pTab = begin(); pTab != end(); ++pTab)
+ {
+ TMLCompDataTable::TMLCompDataSubTable* sub = (*pTab)->FindSubTable(aName);
+ if (sub)
+ return sub;
+ }
+
+ return 0;
+ }
+
+
+void TMLCompData::Merge(TMLCompData& aOther)
+ {
+ iName = aOther.iName;
+ iCanBeMirror |= aOther.iCanBeMirror; // in the case of an elaf layout merging onto an abrw layout, the chirality will be preserved
+ MergeComponents(aOther);
+ }
+
+void TMLCompData::MergeComponents(TMLCompData& aOther)
+ {
+ for (TMLComponents::iterator pOtherLine = aOther.iComponents.begin(); pOtherLine != aOther.iComponents.end(); ++pOtherLine)
+ {
+ TMLCompDataLine& otherLine = *(pOtherLine->second);
+ TMLCompDataLine* found = FindComponent(otherLine.iName);
+ if(found)
+ {
+ found->Merge(otherLine);
+ }
+ else
+ {
+ TMLCompDataLine* newLine = new TMLCompDataLine(otherLine);
+ iComponents.insert(make_pair(otherLine.iId, newLine));
+ }
+ }
+ }
+
+void TMLCompData::Compile()
+ {
+ CreateTables();
+
+ // now add a special table for the screen contents
+ TMLCompDataTable* topTab = new TMLCompDataTable(this);
+ topTab->iId = -1;
+ topTab->iName = KCompDataKeywordScreenContents;
+
+ // then insert each line into its parent
+ for (TMLComponents::iterator pComp2 = iComponents.begin(); pComp2 != iComponents.end(); ++pComp2)
+ {
+ TMLCompDataLine& line = *(pComp2->second);
+ if(line.iType == TMLCompDataLine::EScreenComponent)
+ {
+ line.iParentTable = topTab;
+ topTab->push_back(&line);
+ }
+ else
+ {
+ bool parentFound = false;
+ int parentId = 0;
+ if(line.iParentInfo)
+ {
+ TMLCompDataParentInfo& parentInfo = *(line.iParentInfo);
+ TMLCompDataParentInfoSelector& selector = (parentInfo.begin())->second; // we ignore the varieties for now
+ parentId = selector.iParentId;
+ TMLCompDataTable* parentTable = FindTable(parentId);
+ TMLCompDataLine* parentLine = iComponents[parentId];
+ if(parentTable)
+ {
+ line.iParentTable = parentTable;
+ // copy the pointer from the components table
+ parentTable->push_back(&line);
+ parentFound = true;
+ // now insert the table into its place in the tree
+ parentTable->iParentLine = iComponents[parentId];
+ }
+ else
+ {
+ parentFound = false;
+ }
+ }
+ if(!parentFound)
+ {
+ string errorText = string(" TMLCompData::Compile() - can't find parent component: ");
+ errorText += CdlTkUtil::IntToString(parentId);
+ throw GeneralErr(errorText);
+ }
+ }
+ }
+ push_back(topTab);
+
+ // remember not to delete the components, as we have taken copies!
+ iComponents.clear();
+
+ // now compile the tables
+ iterator pTab;
+ for (pTab = begin(); pTab != end(); ++pTab)
+ (*pTab)->Compile();
+
+ // now sort the tables
+ sort(begin(), end(), TMLCompDataTable::lessthan);
+ }
+
+void TMLCompData::CreateTables()
+ {
+ // from the list of components, first create a table for each pane
+ for (TMLComponents::iterator pComp = iComponents.begin(); pComp != iComponents.end(); ++pComp)
+ {
+ TMLCompDataLine& line = *(pComp->second);
+ switch(line.iType)
+ {
+ case TMLCompDataLine::EScreenComponent:
+ case TMLCompDataLine::EContainerComponent:
+ case TMLCompDataLine::EPaneComponent:
+ {
+ TMLCompDataTable* tab = new TMLCompDataTable(this);
+ tab->iId = line.iId;
+ tab->iName = line.iName;
+ push_back(tab);
+ break;
+ }
+ case TMLCompDataLine::EGraphicComponent:
+ case TMLCompDataLine::ETextComponent:
+ {
+ // text and graphic components are not panes
+ // and are therefore not represented in our internal object model as tables
+ break;
+ }
+ default:
+ {
+ cout << "TMLCompData::CreateTables() - uncategorised component\n";
+ break;
+ }
+ }
+ }
+ }
+
+void TMLCompData::DeleteComponents()
+ {
+ for (TMLComponents::iterator pComp = iComponents.begin(); pComp != iComponents.end(); ++pComp)
+ delete pComp->second;
+ }
+
+// End of File