uidesigner/com.nokia.carbide.cpp.uiq.components/components/srcgenLibrary.js
changeset 0 fb279309251b
equal deleted inserted replaced
-1:000000000000 0:fb279309251b
       
     1 /*
       
     2 * Copyright (c) 2006 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 the License "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("renderLibrary.js")
       
    20 
       
    21 /**
       
    22  * Create a contribution that sets a property if its value
       
    23  * is not equal to a given default.  
       
    24  * @param phase the phase to supply
       
    25  * @param indent extra indentation to add (i.e. 1 if inside an "if")
       
    26  * @param instanceMemberName the name of the member variable
       
    27  * @param propertyValue the current value of the property
       
    28  * @param defaultValue the value considered the default
       
    29  * @param format a format string for setting the property, where
       
    30  *		{0} is substituted with instanceMemberName and 
       
    31  *		{1} is substituted with the propertyValue
       
    32  * @return a contribution, or null
       
    33  */
       
    34 function createSetPropertyForPhase(contribs, phase, indent, instanceMemberName, 
       
    35 			propertyValue, defaultValue, format) {
       
    36 	if (propertyValue != defaultValue) {
       
    37 		contrib = Engine.createContributionForPhase(phase);
       
    38 		contrib.indentAdjust(indent);
       
    39 		contrib.setFormattedText(format, new Array( instanceMemberName, propertyValue) );
       
    40 		return contrib;
       
    41 	}
       
    42 	return null;
       
    43 }
       
    44 
       
    45 /**
       
    46  * Generate a contribution that sets a property if its value
       
    47  * is not equal to a given default.  
       
    48  * @param contribs the contribution list
       
    49  * @param phase the phase to supply
       
    50  * @param indent extra indentation to add (i.e. 1 if inside an "if")
       
    51  * @param instanceMemberName the name of the member variable
       
    52  * @param propertyValue the current value of the property
       
    53  * @param defaultValue the value considered the default
       
    54  * @param format a format string for setting the property, where
       
    55  *		{0} is substituted with instanceMemberName and 
       
    56  *		{1} is substituted with the propertyValue
       
    57  * @param checkNull if true, insert check for null instance around sette
       
    58  */
       
    59 function setPropertyForPhase(contribs, phase, indent, instanceMemberName, 
       
    60 			propertyValue, defaultValue, format, checkNull) {
       
    61 	contrib = createSetPropertyForPhase(contribs, phase, indent, 
       
    62 			instanceMemberName, propertyValue, defaultValue, format);
       
    63 	if (contrib == null)
       
    64 		return;
       
    65 	if (checkNull) {
       
    66 		acontrib = Engine.createContributionForPhase(phase);
       
    67 		acontrib.indentAdjust(indent);
       
    68 		acontrib.setFormattedText("if ( {0} )\n", [ instanceMemberName ]);
       
    69 		contribs.add(acontrib);
       
    70 		
       
    71 		acontrib = Engine.createContributionForPhase(phase);
       
    72 		acontrib.indentAdjust(indent+1);
       
    73 		acontrib.setText("{\n");
       
    74 		contribs.add(acontrib);
       
    75 		
       
    76 		contribs.add(contrib);
       
    77 		
       
    78 		acontrib = Engine.createContributionForPhase(phase);
       
    79 		acontrib.indentAdjust(indent+1);
       
    80 		acontrib.setText("}\n");
       
    81 		contribs.add(acontrib);
       
    82 	} else {
       
    83 		contribs.add(contrib);
       
    84 	}
       
    85 }
       
    86 
       
    87 /**
       
    88  * Generate a set of contributions to set multiple possible
       
    89  * properties.
       
    90  * Like #setPropertyForPhase(), where the 5th and later arguments
       
    91  * are taken in groups of three as [propertyValue, defaultValue, format].
       
    92  */
       
    93 function setPropertiesForPhase(contribs, phase, indent, instanceMemberName, checkNull) {
       
    94 	var ourContribStr = "";
       
    95 	var any = false;
       
    96 	var innerIndent = indent + (checkNull ? 1 : 0);
       
    97 	for (var h = 5; h < arguments.length; h += 3) {
       
    98 		contrib = createSetPropertyForPhase(contribs, phase, innerIndent, instanceMemberName,
       
    99 			arguments[h], arguments[h+1], arguments[h+2]);
       
   100 		if (contrib == null)
       
   101 			continue;
       
   102 		if (!any && checkNull) {
       
   103 			acontrib = Engine.createContributionForPhase(phase);
       
   104 			acontrib.indentAdjust(indent);
       
   105 			acontrib.setFormattedText("if ( {0} )\n", [ instanceMemberName ]);
       
   106 			ourContribStr = acontrib.getText();
       
   107 			
       
   108 			acontrib = Engine.createContributionForPhase(phase);
       
   109 			acontrib.indentAdjust(indent+1);
       
   110 			acontrib.setText("\t" + "{\n");
       
   111 			ourContribStr = ourContribStr + acontrib.getText();
       
   112 			
       
   113 			any	= true;
       
   114 		}
       
   115 		ourContribStr = ourContribStr + "\t" + contrib.getText();
       
   116 	}
       
   117 
       
   118 	if (any && checkNull) {
       
   119 		acontrib = Engine.createContributionForPhase(phase);
       
   120 		acontrib.indentAdjust(indent+1);
       
   121 		acontrib.setText("\t" + "}\n");
       
   122 		ourContribStr = ourContribStr + acontrib.getText();
       
   123 	}
       
   124 	acontrib = Engine.createContributionForPhase(phase);
       
   125 	acontrib.indentAdjust(indent);
       
   126 	acontrib.setText(ourContribStr);
       
   127 	contribs.add(acontrib);
       
   128 }
       
   129 
       
   130 /**
       
   131  *	Get the base filename
       
   132  *	@param path a path
       
   133  */
       
   134 function getBaseFileName(path) {
       
   135 	var idx = path.lastIndexOf('/');
       
   136 	if (idx >= 0)
       
   137 		base = path.substring(idx+1);
       
   138 	else {
       
   139 		idx = path.lastIndexOf('\\');
       
   140 		if (idx >= 0)
       
   141 			base = path.substring(idx+1);
       
   142 		else
       
   143 			base = path;
       
   144 	}
       
   145 	idx = base.lastIndexOf('.');
       
   146 	if (idx >= 0)
       
   147 		base = base.substring(0, idx);
       
   148 		
       
   149 	return base;
       
   150 }
       
   151 
       
   152 /**
       
   153  *	Get the bitmap header file
       
   154  *	@param path the system MBM/MIF name from the image.bmpfile property
       
   155  */
       
   156 function getBitmapHeaderName(path) {
       
   157 	var base = getBaseFileName(path);
       
   158 	base = base + ".mbg";	
       
   159 	return base.toLowerCase();
       
   160 }
       
   161 
       
   162 function addContrib(contribs, phase, loc, indent, text) {
       
   163 	var c;
       
   164 	if (phase != null)
       
   165 		c = Engine.createContributionForPhase(phase);
       
   166 	else
       
   167 		c = Engine.createContributionForLocation(loc);
       
   168 	c.setText(text);
       
   169 	c.indentAdjust(indent);
       
   170 	contribs.add(c);
       
   171 }
       
   172 
       
   173 function addFormattedContrib(contribs, phase, loc, indent, format, args) {
       
   174 	var c;
       
   175 	if (phase != null)
       
   176 		c = Engine.createContributionForPhase(phase);
       
   177 	else
       
   178 		c = Engine.createContributionForLocation(loc);
       
   179 	c.setFormattedText(format, args);
       
   180 	c.indentAdjust(indent);
       
   181 	contribs.add(c);
       
   182 }
       
   183 
       
   184 /**
       
   185  *	Get the nearest enclosing instance that defines a class.
       
   186  */
       
   187 function getClassHolder(instance) {
       
   188 	while (instance != null && !instance.properties.className) {
       
   189 		instance = instance.parent;
       
   190 	}
       
   191 	return instance;
       
   192 }
       
   193 
       
   194 /**
       
   195  *	Get the table of multi-image filenames to literal names
       
   196  */
       
   197 function getFilenameToLiteralTable(instance) {
       
   198 	var holder = getClassHolder(instance);
       
   199 	var key = "ImageSupport.filenameToLiteralTable:" + holder;
       
   200 	var table = Engine.getGlobalDictionary().get(key);
       
   201 	if (table == null) {
       
   202 		table = new java.util.HashMap();
       
   203 		Engine.getGlobalDictionary().put(key, table);
       
   204 	}
       
   205 	return table;
       
   206 }
       
   207 
       
   208 /**
       
   209  *	Get an identifier name from a MBM/MIF filepath
       
   210  */
       
   211 function makeLiteralIdentifier(map, path) {
       
   212 	// no need to uniquify, as the base mbmdef/mifdef name must be unique as well
       
   213 	var base = getBaseFileName(path);
       
   214 	var litname = "K" + base + "File";
       
   215 	return litname;
       
   216 }
       
   217 
       
   218 /**
       
   219  *	Prepare a container for sourcegen that involves generating
       
   220  *	image properties.  We need to ensure the MBM/MIF filename for
       
   221  *	an image is emitted as a constant only once.
       
   222  */
       
   223 function resetImagePropertyState(instance) {
       
   224 	var classHolder = getClassHolder(instance);
       
   225 	classHolder.filenameToLiteralTable = new java.util.HashMap();
       
   226 }
       
   227 
       
   228 /**
       
   229  *	Tell if an image property is set.  If not, it should be ignored.
       
   230  */		
       
   231 function isImagePropertySet(imageProperty) {
       
   232 	return imageProperty.bmpfile != "" 
       
   233 		&& imageProperty.bmpid != "";
       
   234 }
       
   235 
       
   236 /** 
       
   237  *	Tell if we support scaling at all
       
   238  */
       
   239 function isScalingIcons() {
       
   240 	var version = getComponentVersions();
       
   241 	if (version.getMajor() >= 3)
       
   242 		return true;
       
   243 	if (version.getMajor() == 2 && version.getMinor() >= 8) {
       
   244 		appUi = getRootModelInstanceOfType("com.nokia.sdt.series60.CAknAppUi");
       
   245 		if (appUi != null)
       
   246 			return appUi.properties.layoutAware;
       
   247 	}
       
   248 	return false;
       
   249 }
       
   250 
       
   251 /**
       
   252  *	Set up contributions that set up an image property given
       
   253  *	its compound property.  This uses CFbsBitmap* objects and
       
   254  *	thus allows for resizing behavior.  Use a separate routine if
       
   255  *	setting up multiple images, since the repeated code for SVG setup
       
   256  *	can get quite long.
       
   257  *	@param contribs the contributions to append to
       
   258  *	@param instance instance the image is for (used to find the class)
       
   259  *	@param phase primary phase to write to (or null, loc must be set)
       
   260  *	@param loc primary location to write to (or null, phase must be set)
       
   261  *	@param indent indentation adjust
       
   262  *	@param imageProperty the property value
       
   263  *	@param aspectOption the appropriate enumeration for aspect ratio handling (or null)
       
   264  *	@param bitmapPattern when only a bitmap is set,
       
   265  *		a MessageFormat string to be substituted with arguments ([ CFbsBitmap* ])
       
   266  *	@param bitmapAndMaskPattern when a bitmap and mask is set,
       
   267  *		a MessageFormat string to be substituted with arguments (or null)
       
   268  *		([ CFbsBitmap*, CFbsBitmap* ])
       
   269  *	@param theSize text representing the TSize argument (e.g. "control->Size()" or "TSize(45, 66)")
       
   270  *			or null to use the image's real size
       
   271  */
       
   272 function setupImageFromPropertyViaCFbsBitmap(contribs, instance, phase, loc, indent,
       
   273 		imageProperty, aspectOption, 
       
   274 		bitmapPattern, bitmapAndMaskPattern, theSize) {
       
   275 
       
   276 	var version = getComponentVersions();
       
   277 	var contrib;
       
   278 
       
   279 	// moved here to precede system includes of .mbg files	
       
   280 	var isSVG = imageProperty.editableValue.isSVG();
       
   281 
       
   282 	if (isScalingIcons() || isSVG) {
       
   283 		// get icon utilities header
       
   284 		addContrib(contribs, "MainSystemIncludes", loc, 0,
       
   285 			"#include <akniconutils.h>\n");
       
   286 	}
       
   287 	
       
   288 	if (imageProperty.bmpfile != "") {
       
   289 		// make the literal string for the filename
       
   290 		var table = getFilenameToLiteralTable(instance);
       
   291 		var litname = table.get(imageProperty.bmpfile);
       
   292 		if (!litname) {
       
   293 			litname = makeLiteralIdentifier(table, imageProperty.bmpfile);
       
   294 			addContrib(contribs, "MainConstants", null, 0,
       
   295 				"_LIT( " + litname +", \"" + 
       
   296 					TextUtils.escape(imageProperty.bmpfile, '"') + "\" );\n");
       
   297 	
       
   298 			// get the mbg header
       
   299 			addContrib(contribs, "MainSystemIncludes", null, 0,
       
   300 				"#include <" + getBitmapHeaderName(imageProperty.bmpfile) + ">\n");
       
   301 	
       
   302 			table.put(imageProperty.bmpfile, litname);
       
   303 		}
       
   304 	}
       
   305 
       
   306 	if (!isScalingIcons() && !isSVG) {
       
   307 		// only unscalable bitmaps allowed, and initialized via CFbsBitmap
       
   308 		indent++;
       
   309 		addContrib(contribs, phase, loc, indent,
       
   310 			"{\n");
       
   311 		if (bitmapAndMaskPattern != null 
       
   312 				&& imageProperty.bmpfile != ""
       
   313 				&& imageProperty.bmpmask != "" 
       
   314 				&& imageProperty.bmpid != "") {
       
   315 			addContrib(contribs, phase, loc, indent,
       
   316 				"CFbsBitmap* bitmap = iEikonEnv->CreateBitmapL( " + litname + ", " + imageProperty.bmpid + " );\n"
       
   317 				);
       
   318 			addContrib(contribs, phase, loc, indent,
       
   319 				"CFbsBitmap* mask = iEikonEnv->CreateBitmapL( " + litname + ", " + imageProperty.bmpmask + " );\n"
       
   320 				);
       
   321 			
       
   322 			addFormattedContrib(contribs, phase, loc, indent,
       
   323 				bitmapAndMaskPattern, [ "bitmap", "mask" ]);
       
   324 		}
       
   325 		else if (bitmapPattern != null) {
       
   326 			if (imageProperty.bmpfile != "" && imageProperty.bmpid != "") {
       
   327 				addContrib(contribs, phase, loc, indent,
       
   328 					"CFbsBitmap* bitmap = iEikonEnv->CreateBitmapL( " + litname + ", " + imageProperty.bmpid + " );\n"
       
   329 					);
       
   330 			} else {
       
   331 				// no image, but at least a bitmap is required
       
   332 				addContrib(contribs, phase, loc, indent,
       
   333 					"CFbsBitmap* bitmap = new (ELeave) CFbsBitmap;\n"
       
   334 					);
       
   335 			}						
       
   336 			addFormattedContrib(contribs, phase, loc, indent,
       
   337 				bitmapPattern, [ "bitmap" ]);
       
   338 		}
       
   339 
       
   340 		addContrib(contribs, phase, loc, indent,
       
   341 			"}\n");
       
   342 		indent--;
       
   343 		
       
   344 	} else {
       
   345 		// S60 >= 3.0
       
   346 		
       
   347 		indent++;
       
   348 
       
   349 		addContrib(contribs, phase, loc, indent,
       
   350 			"{\n");
       
   351 
       
   352 		var sizeArg = theSize;
       
   353 		if (sizeArg == null)
       
   354 			sizeArg = "size"; 	// for SVG 
       
   355 
       
   356 		if (imageProperty.bmpfile != "") {		
       
   357 			// load the bitmap and/or mask
       
   358 			addContrib(contribs, phase, loc, indent,
       
   359 				"CFbsBitmap *bitmap, *mask;\n");
       
   360 				
       
   361 			addContrib(contribs, phase, loc, indent,
       
   362 				"AknIconUtils::CreateIconL( bitmap, mask,\n"+
       
   363 				"\t\t" + litname + ", " + 
       
   364 				((bitmapPattern != null && imageProperty.bmpid != "") ?
       
   365 					imageProperty.bmpid : "-1") + 
       
   366 					", " +
       
   367 				((bitmapAndMaskPattern != null && imageProperty.bmpmask != "") ?
       
   368 					imageProperty.bmpmask : "-1") +
       
   369 					" );\n");
       
   370 					
       
   371 			// prepare to issue two calls needing SVG info
       
   372 			if (isSVG && theSize == null) {
       
   373 				addContrib(contribs, phase, loc, indent,
       
   374 					"TSize size;\n"+
       
   375 					"AknIconUtils::PreserveIconData( bitmap );\n"+
       
   376 					//"AknIconUtils::PreserveIconData( mask );\n"+
       
   377 					"");
       
   378 			}
       
   379 
       
   380 		} else {
       
   381 			// no image, but at least a bitmap WITH CONTENT is required
       
   382 			addContrib(contribs, phase, loc, indent,
       
   383 				"CFbsBitmap *bitmap = new (ELeave) CFbsBitmap;\n"+
       
   384 				"bitmap->Create( TSize( 1, 1), EGray2 );\n");
       
   385 		}
       
   386 		
       
   387 		// set the size
       
   388 		var aspectText;
       
   389 		if (aspectOption != null && aspectOption != "")
       
   390 			aspectText = ", " + aspectOption;
       
   391 		else
       
   392 			aspectText = ", EAspectRatioNotPreserved";
       
   393 
       
   394 		if (imageProperty.bmpfile != "") {		
       
   395 			if (isSVG && theSize == null) {
       
   396 				// get the size
       
   397 				addContrib(contribs, phase, loc, indent,
       
   398 					"AknIconUtils::GetContentDimensions( bitmap, size );\n");
       
   399 			}
       
   400 		}
       
   401 
       
   402 		if (bitmapAndMaskPattern != null 
       
   403 				&& imageProperty.bmpfile != ""
       
   404 				&& imageProperty.bmpmask != "" 
       
   405 				&& imageProperty.bmpid != "") {
       
   406 
       
   407 			addContrib(contribs, phase, loc, indent,
       
   408 				"AknIconUtils::SetSize( bitmap, " + sizeArg + aspectText + " );\n");
       
   409 			addContrib(contribs, phase, loc, indent,
       
   410 				"AknIconUtils::SetSize( mask, " + sizeArg + aspectText + " );\n");
       
   411 
       
   412 			addFormattedContrib(contribs, phase, loc, indent,
       
   413 				bitmapAndMaskPattern, [ "bitmap", "mask" ]);
       
   414 					
       
   415 		} else if (bitmapPattern != null) {
       
   416 			addContrib(contribs, phase, loc, indent,
       
   417 				"AknIconUtils::SetSize( bitmap, " + theSize + aspectText + " );\n");
       
   418 
       
   419 			addFormattedContrib(contribs, phase, loc, indent,
       
   420 				bitmapPattern, [ "bitmap" ]);
       
   421 		}
       
   422 
       
   423 		if (isSVG && theSize == null) {
       
   424 			addContrib(contribs, phase, loc, indent,
       
   425 				"AknIconUtils::DestroyIconData( bitmap );\n");
       
   426 		}
       
   427 		
       
   428 		addContrib(contribs, phase, loc, indent,
       
   429 			"}\n");
       
   430 		
       
   431 		indent--;
       
   432 	}
       
   433 }
       
   434 
       
   435 /**
       
   436  *	Set up contributions that set up an image property given
       
   437  *	its compound property.  This passes arguments to a function
       
   438  *	which takes the (TDesc aFileName, TInt bmpid, TInt maskid)
       
   439  *	arguments.  Image resizing is not allowed.
       
   440  *	@param contribs the contributions to append to
       
   441  *	@param instance instance the image is for (used to find the class)
       
   442  *	@param phase primary phase to write to (or null, loc must be set)
       
   443  *	@param loc primary location to write to (or null, phase must be set)
       
   444  *	@param indent indentation adjust
       
   445  *	@param imageProperty the compound property providing bmpfile, bmpid, bmpmask
       
   446  *	@param bitmapPattern when only a bitmap is set,
       
   447  *		a MessageFormat string to be substituted with arguments
       
   448  *		([ filename, id ])
       
   449  *	@param bitmapAndMaskPattern when a bitmap and mask is set,
       
   450  *		a MessageFormat string to be substituted with arguments (or null)
       
   451  *		([ filename, id, maskid ])
       
   452  */
       
   453 function setupImageFromPropertyViaTuple(contribs, instance, phase, loc, indent,
       
   454 		imageProperty,
       
   455 		bitmapPattern, bitmapAndMaskPattern) {
       
   456 
       
   457 	if (!isImagePropertySet(imageProperty))
       
   458 		return;
       
   459 		
       
   460 	var version = getComponentVersions();
       
   461 	var contrib;
       
   462 	
       
   463 	// make the literal string for the filename
       
   464 	var table = getFilenameToLiteralTable(instance);
       
   465 	var litname = table.get(imageProperty.bmpfile);
       
   466 	if (!litname) {
       
   467 		litname = makeLiteralIdentifier(table, imageProperty.bmpfile);
       
   468 		addContrib(contribs, "MainConstants", null, 0,
       
   469 			"_LIT( " + litname +", \"" + 
       
   470 				TextUtils.escape(imageProperty.bmpfile, '"') + "\" );\n");
       
   471 
       
   472 		// get the mbg header
       
   473 		addContrib(contribs, "MainSystemIncludes", null, 0,
       
   474 			"#include <" + getBitmapHeaderName(imageProperty.bmpfile) + ">\n");
       
   475 
       
   476 		table.put(imageProperty.bmpfile, litname);
       
   477 	}
       
   478 		
       
   479 	if (bitmapAndMaskPattern != null 
       
   480 			&& imageProperty.bmpmask != "") {
       
   481 		
       
   482 		addFormattedContrib(contribs, phase, loc, indent,
       
   483 			bitmapAndMaskPattern, [ litname, imageProperty.bmpid, imageProperty.bmpmask ]);
       
   484 	}
       
   485 	else if (bitmapPattern != null) {
       
   486 		addFormattedContrib(contribs, phase, loc, indent,
       
   487 			bitmapPattern, [ litname, imageProperty.bmpid ]);
       
   488 	}
       
   489 	
       
   490 }
       
   491 
       
   492 /**
       
   493  *	Create a method that loads and scales SVG or BMP icons, for use when
       
   494  *	multiple icons are loaded at once.  This assumes the function defined in
       
   495  *	LoadAndScaleIconL.inc.  For S60 2.8 or newer.
       
   496  */
       
   497 function defineIconLoadingRoutines(contribs, location, className) { 
       
   498 	// get icon utilities headers.  
       
   499 	addContrib(contribs, "HeaderIncludes", null, 0,
       
   500 		"#include <akniconutils.h>\n");
       
   501 	addContrib(contribs, "HeaderIncludes", null, 0,
       
   502 		"#include <gulicon.h>\n");
       
   503 		
       
   504 	//// needs to be permanent or else it's duplicated
       
   505 	//addContrib(contribs, "UserHandlers", null, 0,
       
   506 	addContrib(contribs, "ClassMethods", null, 0,
       
   507 		"static CGulIcon* LoadAndScaleIconL(\n"+
       
   508 		"\t\tconst TDesC& aFileName,\n"+
       
   509 		"\t\tTInt aBitmapId,\n"+
       
   510 		"\t\tTInt aMaskId,\n"+
       
   511 		"\t\tTSize* aSize,\n"+
       
   512 		"\t\tTScaleMode aScaleMode );\n"
       
   513 	);
       
   514 	
       
   515 	// force the location to be instantiated
       
   516 	addContrib(contribs, null, location, 0, "");
       
   517 	return;
       
   518 }
       
   519 
       
   520 var alignmentMap = {
       
   521 	"EHLeft+EVTop" : "EHLeftVTop",
       
   522 	"EHLeft+EVCenter" : "EHLeftVCenter",
       
   523 	"EHLeft+EVBottom" : "EHLeftVBottom",
       
   524 	"EHCenter+EVTop" : "EHCenterVTop",
       
   525 	"EHCenter+EVCenter" : "EHCenterVCenter",
       
   526 	"EHCenter+EVBottom" : "EHCenterVBottom",
       
   527 	"EHRight+EVTop" : "EHRightVTop",
       
   528 	"EHRight+EVCenter" : "EHRightVCenter",
       
   529 	"EHRight+EVBottom" : "EHRightVBottom"
       
   530 };
       
   531 
       
   532 function getTGulAlignmentValue(horiz, vert) {
       
   533 	return alignmentMap[horiz+"+"+vert];	
       
   534 }
       
   535 
       
   536 //////////////////////////
       
   537 
       
   538 /**
       
   539  *	Get the table of unique images in an icon array
       
   540  *	@return an ImageList
       
   541  */
       
   542 function getImageList(instance) {
       
   543 	var key = "srcgenLibrary.ImageList:" + instance.name;
       
   544 	var table = Engine.getGlobalDictionary().get(key);
       
   545 	if (table == null) {
       
   546 		table = new ImageList(instance);
       
   547 		Engine.getGlobalDictionary().put(key, table);
       
   548 	}
       
   549 	return table;
       
   550 }
       
   551 
       
   552 
       
   553 /**
       
   554  *	This is a prototype used to track arrays of icons.  
       
   555  *	Create an instance of the class and populate it with image
       
   556  *	properties, then generate contributions that create a
       
   557  *	CArrayPtr<CGulIcon> array, then look up indices of image
       
   558  *	properties either by index or generated enum.
       
   559  *
       
   560  *	@param ownerInstance the instance that owns all the images
       
   561  */
       
   562 function ImageList(ownerInstance) {
       
   563 	this.ownerInstance = ownerInstance;
       
   564 	this.imageMap = new java.util.LinkedHashMap();
       
   565 	this.enumSet = new java.util.LinkedHashSet();
       
   566 	this.imageIdx = 0;
       
   567 	this.lastEnum = "0";
       
   568 }
       
   569 
       
   570 ImageList.prototype.getImagePropertyKey = function(imageProperty) {
       
   571 	if (isImagePropertySet(imageProperty)) {
       
   572 		return imageProperty.bmpfile + "|" + imageProperty.bmpid + "|" + imageProperty.bmpmask;
       
   573 	} else {
       
   574 		return null;
       
   575 	}
       
   576 }
       
   577 
       
   578 ImageList.prototype.uniquifyEnum = function(enm) {
       
   579 	var idx = 1;
       
   580 	var base = enm;
       
   581 	while (this.enumSet.contains(enm)) {
       
   582 		enm = base + (++idx);
       
   583 	}
       
   584 	return enm;
       
   585 }
       
   586 
       
   587 IL_PROPERTY_INDEX = 0;
       
   588 IL_INDEX_INDEX = 1;
       
   589 IL_ENUM_INDEX = 2;
       
   590 
       
   591 /**
       
   592  *	Register an image property.  Only adds if unique.
       
   593  *	@param instance the instance containing the property
       
   594  *	@param property the property ID
       
   595  */
       
   596 ImageList.prototype.registerImageProperty = function(imageProperty) {
       
   597 	var key = this.getImagePropertyKey(imageProperty);
       
   598 	if (key != null && !this.imageMap.containsKey(key)) {
       
   599 		var base = imageProperty.bmpid;
       
   600 		if (base == "")
       
   601 			base = imageProperty.bmpmask;
       
   602 		if (base.substring(0, 4) == "EMbm")
       
   603 			base = base.substring(4);
       
   604 		
       
   605 		var enm = "E" + titleCase(this.ownerInstance.name) + base + "Index";
       
   606 		enm = this.uniquifyEnum(enm);
       
   607 		this.enumSet.add(enm);
       
   608 		this.lastEnum = enm;
       
   609 			
       
   610 		this.imageMap.put(key, [imageProperty, this.imageIdx++, enm]);
       
   611 	}
       
   612 }
       
   613 
       
   614 ImageList.prototype.getSystemImageKey = function(bitmap, mask) {
       
   615 	if (bitmap == null || bitmap.length == 0)
       
   616 		return null;
       
   617 
       
   618 	var file = "KAvkonBitmapFile";	// constant in aknconsts.h
       
   619 	var prefix = "EMbmAvkon";
       
   620 	var key = file 
       
   621 		+ "|" 
       
   622 		+ (bitmap.length > 0 ? prefix + titleCase(bitmap) : "") 
       
   623 		+ "|" 
       
   624 		+ (mask.length > 0 ? prefix + titleCase(mask) : "");
       
   625 	return key;
       
   626 }
       
   627 
       
   628 /**
       
   629  *	Register an Avkon system image (only added if unique).  
       
   630  */
       
   631 ImageList.prototype.registerAvkonSystemImage = function(bitmap, mask) {
       
   632 	var key = this.getSystemImageKey(bitmap, mask);
       
   633 	if (key != null && !this.imageMap.containsKey(key)) {
       
   634 		var enm = "E" + titleCase(this.ownerInstance.name) 
       
   635 			+ "Avkon" + titleCase(bitmap != null ? bitmap : mask) 
       
   636 			+ "Index";
       
   637 		enm = this.uniquifyEnum(enm);
       
   638 		this.lastEnum = enm;
       
   639 
       
   640 		this.imageMap.put(key, [null, this.imageIdx++, enm]);
       
   641 	}
       
   642 }
       
   643 
       
   644 /**
       
   645  *	Get the icon index for the given image.
       
   646  */
       
   647 ImageList.prototype.getListIconIndexForProperty = function(imageProperty) {
       
   648 	var key = this.getImagePropertyKey(imageProperty);
       
   649 	var value = this.imageMap.get(key);
       
   650 	if (value != null)
       
   651 		return value[IL_INDEX_INDEX];
       
   652 	else
       
   653 		return -1;
       
   654 }
       
   655 
       
   656 /**
       
   657  *	Get the enumerator for the given image.
       
   658  */
       
   659 ImageList.prototype.getListIconEnumForProperty = function(imageProperty, getEnum) {
       
   660 	var key = this.getImagePropertyKey(imageProperty);
       
   661 	var value = this.imageMap.get(key);
       
   662 	if (value != null)
       
   663 		return value[IL_ENUM_INDEX];
       
   664 	else
       
   665 		return null;
       
   666 }
       
   667 
       
   668 /**
       
   669  *	Get the number of images, also the upper bound of the indices
       
   670  */
       
   671 ImageList.prototype.getImageCount = function() {
       
   672 	return this.imageIdx;
       
   673 }
       
   674 
       
   675 ImageList.prototype.getLastEnumerator = function() {
       
   676 	return this.lastEnum;
       
   677 }
       
   678 
       
   679 /**
       
   680  *	Generate code to set up a CGulIcon icon array.  Since S60 doesn't
       
   681  *	tolerate empty arrays, the generated code allocates the array only if needed,
       
   682  *	leaving it on the cleanup stack.  The caller of this code/routine
       
   683  *	needs to examine the return value and handle cleaning up appropriately.
       
   684  *	@param contribs
       
   685  *	@param iconsVar name of array variable to create (must be declared)
       
   686  *	@param location the function to add code to
       
   687  *	@param mainLocation preferably owned section in main file to add function to if needed
       
   688  *	@param instance instance to search upwards for owning class
       
   689  *	@param isScaling true if scaling bitmaps and icons, false otherwise
       
   690  *  @return true if icon array allocated
       
   691  */
       
   692 ImageList.prototype.generateSetupIconArrayL = function(contribs, iconsVar, location, mainLocation, instance, isScaling) {
       
   693 	// must not generate a zero-size array or set an empty icon array
       
   694 	var anyIcons = false;
       
   695 	
       
   696 	var iconVar = (iconsVar.match(".*s") ? iconsVar.substring(0, iconsVar.length - 1) : iconsVar + "_instance");
       
   697 	
       
   698 	for (var iter = this.imageMap.entrySet().iterator(); iter.hasNext(); ) {
       
   699 		var entry = iter.next();
       
   700 		var key = entry.getKey();
       
   701 		var value = entry.getValue();
       
   702 		var property = value[IL_PROPERTY_INDEX];
       
   703 		var index = value[IL_INDEX_INDEX];
       
   704 		var enm = value[IL_ENUM_INDEX];
       
   705 		var granularity = this.enumSet.size() > 0? this.enumSet.size() : 1;
       
   706 
       
   707 		if (!anyIcons) {
       
   708 			addFormattedContrib(contribs, null, location, 0,
       
   709 				 "{0} = new (ELeave) CAknIconArray( {1} );\n",
       
   710 				 [ iconsVar,
       
   711 				 granularity
       
   712 				 ] );
       
   713 		
       
   714 			addFormattedContrib(contribs, null, location,  0,
       
   715 					"CleanupStack::PushL( {0} );\n",
       
   716 					[ iconsVar ]);
       
   717 
       
   718 			if (isScaling) {
       
   719 				defineIconLoadingRoutines(contribs, mainLocation, getClassHolder(instance).properties["className"]);
       
   720 			}
       
   721 
       
   722 			addFormattedContrib(contribs, null, location,  0,
       
   723 					"CGulIcon* {0};\n",
       
   724 					[ iconVar ]);
       
   725 
       
   726 			anyIcons = true;		
       
   727 		}
       
   728 		
       
   729 		//println("querying " + instance + ", property="+property);
       
   730 
       
   731 		// This assumes the user doesn't modify the ordering and
       
   732 		// all enums map evenly to 0...N.
       
   733 		// We can't use ->InsertL or ->ExtendL since they're stupid.
       
   734 		var adder = "->AppendL";
       
   735 		
       
   736 		// Bug 7621: please ensure that a leave in the AppendL doesn't 
       
   737 		// leak the allocated image.
       
   738 		var saveIcon = "CleanupStack::PushL( " + iconVar + " );\n";
       
   739 		var restoreIcon = "CleanupStack::Pop( " + iconVar + " );\n";
       
   740 		var addIcon = iconsVar + adder + "( " + iconVar + " );\n";
       
   741 		var saveAddAndRestore = saveIcon + addIcon + restoreIcon;
       
   742 
       
   743 		contrib = Engine.createContributionForLocation(location);
       
   744 		contrib.setText("// for " + enm + "\n");
       
   745 		contribs.add(contrib);
       
   746 	
       
   747 		if (property == null) {
       
   748 			// system image
       
   749 			var parts = key.split("\\|");
       
   750 			
       
   751 			var contrib = Engine.createContributionForPhase("MainSystemIncludes");
       
   752 			contrib.setText("#include <aknconsts.h>\n");
       
   753 			contribs.add(contrib);
       
   754 
       
   755 			contrib = Engine.createContributionForPhase("MainSystemIncludes");
       
   756 			contrib.setText("#include <avkon.mbg>\n");
       
   757 			contribs.add(contrib);
       
   758 			
       
   759 			var format;
       
   760 			
       
   761 			if (isScaling) {
       
   762 				if (parts[2] != "") {
       
   763 					format = iconVar + " = LoadAndScaleIconL(\n\t\t{0}, {1}, {2},\n\t\tNULL, EAspectRatioPreserved );\n"
       
   764 						+ saveAddAndRestore;
       
   765 				} else {
       
   766 					format = iconVar + " = LoadAndScaleIconL(\n\t\t{0}, {1}, -1,\n\t\tNULL, EAspectRatioPreserved );\n"
       
   767 						+ saveAddAndRestore;
       
   768 				}
       
   769 			} else {
       
   770 				if (parts[2] != "") {
       
   771 					format = iconVar + " = CEikonEnv::Static()->CreateIconL(\n\t\t{0}, {1}, {2} );\n"
       
   772 						+ saveAddAndRestore;
       
   773 				} else {
       
   774 					format = iconVar + " = CEikonEnv::Static()->CreateIconL(\n\t\t{0}, {1} );\n"
       
   775 						+ saveAddAndRestore;
       
   776 				}
       
   777 			}			
       
   778 			contrib = Engine.createContributionForLocation(location);
       
   779 			contrib.setFormattedText(format, parts);
       
   780 			contribs.add(contrib);
       
   781 			
       
   782 		} else {
       
   783 			if (isScaling) {
       
   784 				setupImageFromPropertyViaTuple(contribs, instance, null, location, 0,
       
   785 					property,
       
   786 					iconVar + " = LoadAndScaleIconL(\n\t\t{0}, {1}, -1,\n\t\tNULL, EAspectRatioPreserved );\n"
       
   787 						+ saveAddAndRestore,
       
   788 					iconVar + " = LoadAndScaleIconL(\n\t\t{0}, {1}, {2},\n\t\tNULL, EAspectRatioPreserved );\n"
       
   789 						+ saveAddAndRestore
       
   790 				);
       
   791 			} else {
       
   792 				setupImageFromPropertyViaTuple(contribs, instance, null, location, 0,
       
   793 					property, 
       
   794 					iconVar + " = CEikonEnv::Static()->CreateIconL(\n\t\t{0}, {1} );\n"
       
   795 						+ saveAddAndRestore,
       
   796 					iconVar + " = CEikonEnv::Static()->CreateIconL(\n\t\t{0}, {1}, {2} );\n"
       
   797 						+ saveAddAndRestore);
       
   798 			}
       
   799 		}
       
   800 	}
       
   801 		
       
   802 	if (anyIcons) {
       
   803 		return true;
       
   804 	}
       
   805 	else
       
   806 		return false;
       
   807 }
       
   808 
       
   809 /**
       
   810  *	Generate text to be substituted into an enum{} declaration.
       
   811  */
       
   812 ImageList.prototype.generateImageListEnums = function() {
       
   813 	var text = "";
       
   814 	for (var iter = this.imageMap.entrySet().iterator(); iter.hasNext(); ) {
       
   815 		var entry = iter.next();
       
   816 		var index = entry.getValue()[IL_INDEX_INDEX];
       
   817 		var enm = entry.getValue()[IL_ENUM_INDEX];
       
   818 		text += enm + " = " + index + ",\n";
       
   819 	}
       
   820 	text += "E" + titleCase(this.ownerInstance.name) + "FirstUserImageIndex\n";
       
   821 	return text;
       
   822 }
       
   823 
       
   824 ImageList.prototype.dump = function() {
       
   825 	println("dump of image list: ");
       
   826 	for (var iter = this.imageMap.entrySet().iterator(); iter.hasNext(); ) {
       
   827 		var entry = iter.next();
       
   828 		var key = entry.getKey();
       
   829 		var value = entry.getValue();
       
   830 		var property = value[IL_PROPERTY_INDEX];
       
   831 		var index = value[IL_INDEX_INDEX];
       
   832 
       
   833 		println("key="+key+", property="+property+", index="+index);
       
   834 	}
       
   835 }