PageRenderTime 23ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/modules/utils/source/temple/utils/types/TextFieldUtils.as

http://templelibrary.googlecode.com/
ActionScript | 366 lines | 232 code | 34 blank | 100 comment | 45 complexity | b5c35d43a7acfb122a11ba4b8a34c484 MD5 | raw file
  1. /*
  2. * Temple Library for ActionScript 3.0
  3. * Copyright Š MediaMonks B.V.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. All advertising materials mentioning features or use of this software
  14. * must display the following acknowledgement:
  15. * This product includes software developed by MediaMonks B.V.
  16. * 4. Neither the name of MediaMonks B.V. nor the
  17. * names of its contributors may be used to endorse or promote products
  18. * derived from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY MEDIAMONKS B.V. ''AS IS'' AND ANY
  21. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  22. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  23. * DISCLAIMED. IN NO EVENT SHALL MEDIAMONKS B.V. BE LIABLE FOR ANY
  24. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  25. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  26. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  27. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. *
  31. *
  32. * Note: This license does not apply to 3rd party classes inside the Temple
  33. * repository with their own license!
  34. */
  35. package temple.utils.types
  36. {
  37. import temple.core.debug.log.Log;
  38. import temple.core.debug.objectToString;
  39. import temple.core.errors.TempleError;
  40. import temple.core.errors.throwError;
  41. import temple.utils.FrameDelay;
  42. import flash.display.DisplayObject;
  43. import flash.display.DisplayObjectContainer;
  44. import flash.text.StyleSheet;
  45. import flash.text.TextField;
  46. import flash.text.TextFormat;
  47. import flash.text.TextLineMetrics;
  48. /**
  49. * This class contains some functions for TextFields.
  50. *
  51. * @author Thijs Broerse
  52. */
  53. public final class TextFieldUtils
  54. {
  55. private static const _MAGICAL_TEXTWIDTH_PADDING:Number = 3;
  56. /**
  57. * Inits the give textfield with an autoFormat and sets the defaultTextFormat so you can change the text without losing its formatting
  58. * @param textField The TextField to init
  59. * @param autoSize The autosize to set
  60. */
  61. public static function init(textField:TextField, autoSize:String = null):void
  62. {
  63. textField.defaultTextFormat = textField.getTextFormat();
  64. if (autoSize) textField.autoSize = autoSize;
  65. }
  66. /**
  67. * Trims the text to fit a given textfield.
  68. * @param textField the TextField to set the new text to.
  69. * @param abbreviatedString the text that indicates that trimming has occurred; commonly this is "..."
  70. * @return a Boolean which indicates if the text in the TextField is trimmed.
  71. */
  72. public static function trimTextFieldText(textField:TextField, abbreviatedString:String = "..."):Boolean
  73. {
  74. var text:String = textField.text;
  75. var trimLength:int = text.length;
  76. var trimmed:Boolean;
  77. while (textField.multiline && textField.textHeight > textField.height || !textField.multiline && textField.textWidth + TextFieldUtils._MAGICAL_TEXTWIDTH_PADDING > textField.width)
  78. {
  79. --trimLength;
  80. text = text.substr(0, trimLength);
  81. text += abbreviatedString;
  82. textField.text = text;
  83. trimmed = true;
  84. }
  85. return trimmed;
  86. }
  87. /**
  88. * Trims the htmlText to fit a given textfield.
  89. * @param textField the TextField to set the new text to.
  90. * @param abbreviatedString the text that indicates that trimming has occurred; commonly this is "..."
  91. * @return a Boolean which indicates if the text in the TextField is trimmed.
  92. */
  93. public static function trimTextFieldHTMLText(textField:TextField, abbreviatedString:String = "..."):Boolean
  94. {
  95. var styleSheet:StyleSheet = textField.styleSheet;
  96. textField.styleSheet = null;
  97. var text:String;
  98. var closeTag:uint;
  99. var trimmed:Boolean;
  100. while (textField.multiline && textField.textHeight > textField.height || !textField.multiline && textField.textWidth + TextFieldUtils._MAGICAL_TEXTWIDTH_PADDING > textField.width)
  101. {
  102. text = textField.getXMLText(0, textField.text.length - 1 - abbreviatedString.length);
  103. closeTag = text.lastIndexOf(')</textformat>');
  104. text = text.substr(0, closeTag) + abbreviatedString + text.substr(closeTag);
  105. textField.insertXMLText(0, textField.text.length, text);
  106. trimmed = true;
  107. }
  108. new FrameDelay(function():void { textField.styleSheet = styleSheet; }, 5);
  109. return trimmed;
  110. }
  111. /**
  112. * Creates a new TextField with the same layout
  113. */
  114. public static function copy(textField:TextField):TextField
  115. {
  116. var t:TextField = new TextField();
  117. t.antiAliasType = textField.antiAliasType;
  118. t.autoSize = textField.autoSize;
  119. t.defaultTextFormat = textField.defaultTextFormat;
  120. t.embedFonts = textField.embedFonts;
  121. t.gridFitType = textField.gridFitType;
  122. t.mouseWheelEnabled = textField.mouseWheelEnabled;
  123. t.multiline = textField.multiline;
  124. t.selectable = textField.selectable;
  125. t.sharpness = textField.sharpness;
  126. t.styleSheet = textField.styleSheet;
  127. t.text = textField.text;
  128. t.textColor = textField.textColor;
  129. t.thickness = textField.thickness;
  130. t.type = textField.type;
  131. t.wordWrap = textField.wordWrap;
  132. t.width = textField.width;
  133. t.height = textField.height;
  134. t.x = textField.x;
  135. t.y = textField.y;
  136. t.setTextFormat(textField.getTextFormat());
  137. return t;
  138. }
  139. /**
  140. * Searches for TextField in a DisplayObject and set the TextFormat as Default. In this way the textformat won't changes, when you change the text
  141. *
  142. * @param displayObject The displayObject that contains the TextFields
  143. * @param recursive if set to true all childrens TextFields (and grandchildrens etc) will also be formatted
  144. * @param debug if set to true, debug information of the formatted TextFields will be logged
  145. */
  146. public static function formatTextFields(container:DisplayObjectContainer, recursive:Boolean = true, debug:Boolean = false):void
  147. {
  148. if (container == null) return;
  149. var child:DisplayObject;
  150. var leni:int = container.numChildren;
  151. for (var i:int = 0;i < leni ;i++)
  152. {
  153. child = container.getChildAt(i);
  154. if (child is TextField)
  155. {
  156. TextField(child).defaultTextFormat = TextField(child).getTextFormat();
  157. if (debug) Log.debug("formatTextFields: found TextField '" + TextField(child).name + "', text: '" + TextField(child).text + "'", "temple.utils.types.DisplayObjectContainerUtils");
  158. }
  159. else if (recursive && child is DisplayObjectContainer)
  160. {
  161. TextFieldUtils.formatTextFields(DisplayObjectContainer(child), recursive, debug);
  162. }
  163. }
  164. }
  165. /**
  166. * Searches for TextField in a DisplayObject and set the text to ''.
  167. *
  168. * @param displayObject The displayObject that contains the TextFields
  169. * @param recursive if set to true all childrens TextFields (and grandchildrens etc) will also be formatted
  170. * @param debug if set to true, debug information of the formatted TextFields will be logged
  171. */
  172. public static function emptyTextFields(container:DisplayObjectContainer, recursive:Boolean = true, debug:Boolean = false):void
  173. {
  174. if (container == null) return;
  175. var child:DisplayObject;
  176. var leni:int = container.numChildren;
  177. for (var i:int = 0;i < leni ;i++)
  178. {
  179. child = container.getChildAt(i);
  180. if (child is TextField)
  181. {
  182. if (debug) Log.debug("emptyTextFields: found TextField '" + TextField(child).name + "', text: '" + TextField(child).text + "'", "temple.utils.types.DisplayObjectContainerUtils");
  183. TextField(child).text = '';
  184. }
  185. else if (recursive && child is DisplayObjectContainer)
  186. {
  187. TextFieldUtils.emptyTextFields(DisplayObjectContainer(child), recursive, debug);
  188. }
  189. }
  190. }
  191. /**
  192. * Searches for TextFields in the displaylist and set embedFonts to true.
  193. *
  194. * From Seb Lee-Delisle http://www.sebleedelisle.com/2009/08/font-embedding-wtf-in-flash/
  195. */
  196. public static function embedFontsInTextFields(container:DisplayObjectContainer):void
  197. {
  198. var child:DisplayObject;
  199. for (var i:int = 0;i < container.numChildren;i++)
  200. {
  201. child = container.getChildAt(i);
  202. if (child is DisplayObjectContainer)
  203. {
  204. TextFieldUtils.embedFontsInTextFields(child as DisplayObjectContainer);
  205. }
  206. else if (child is TextField)
  207. {
  208. (child as TextField).embedFonts = true;
  209. }
  210. }
  211. }
  212. /**
  213. * Checks if a TextField uses a TextFormat
  214. */
  215. public static function usesTextFormat(textField:TextField):Boolean
  216. {
  217. return (textField.getTextFormat() != null);
  218. }
  219. public static function usesStyleSheet(textField:TextField):Boolean
  220. {
  221. return (textField.styleSheet != null);
  222. }
  223. /**
  224. * Get the font size of a TextField
  225. */
  226. public static function getFontSize(textField:TextField):Number
  227. {
  228. if (textField.text == "") return 0;
  229. var usesStyleSheet:Boolean = TextFieldUtils.usesStyleSheet(textField);
  230. var usesOneTextFormat:Boolean = TextFieldUtils.usesTextFormat(textField);
  231. if (!usesOneTextFormat && !usesStyleSheet)
  232. {
  233. throwError(new TempleError(TextFieldUtils, "Getting fontSize only works when you use one TextFormat or a StyleSheet"));
  234. }
  235. if (!usesStyleSheet)
  236. {
  237. var textFormat:TextFormat = textField.getTextFormat();
  238. return textFormat.size as Number;
  239. }
  240. else
  241. {
  242. var avarageSize:Number = 0;
  243. var styles:Array = textField.styleSheet.styleNames;
  244. var i:int = styles.length;
  245. while (i--)
  246. {
  247. var styleName:String = styles[i];
  248. var styleObject:Object = textField.styleSheet.getStyle(styleName);
  249. avarageSize += styleObject.fontSize;
  250. }
  251. avarageSize = avarageSize / styles.length;
  252. return avarageSize;
  253. }
  254. }
  255. /**
  256. * Set the fontsize on a TextField
  257. */
  258. public static function setFontSize(textField:TextField, fontSize:Number):void
  259. {
  260. var usesStyleSheet:Boolean = TextFieldUtils.usesStyleSheet(textField);
  261. var usesOneTextFormat:Boolean = TextFieldUtils.usesTextFormat(textField);
  262. if (!usesOneTextFormat && !usesStyleSheet)
  263. {
  264. throwError(new TempleError(TextField, "setting fontSize only works when you use one TextFormat or a StyleSheet"));
  265. }
  266. if (!usesStyleSheet)
  267. {
  268. var textFormat:TextFormat = textField.getTextFormat();
  269. textFormat.size = fontSize;
  270. textField.setTextFormat(textFormat);
  271. }
  272. else
  273. {
  274. // Because stylesheets usualy work with multiple sizes, we use the differance.
  275. var prevFontSize:Number = getFontSize(textField);
  276. var sizeDiff:Number = fontSize - prevFontSize;
  277. var styles:Array = textField.styleSheet.styleNames;
  278. var i:int = styles.length;
  279. while (i--)
  280. {
  281. var styleName:String = styles[i];
  282. var styleObject:Object = textField.styleSheet.getStyle(styleName);
  283. styleObject.fontSize = Number(styleObject.fontSize) + sizeDiff;
  284. textField.styleSheet.setStyle(styleName, styleObject);
  285. }
  286. textField.styleSheet = textField.styleSheet;
  287. }
  288. }
  289. /**
  290. * Sets the font (textFormat and defaultTextFormat) for the given TextField
  291. * @param textField The TextField to set the font on
  292. * @param fontName The name of the font to apply on the TextField
  293. */
  294. public static function setFont(textField:TextField, fontName:String):void
  295. {
  296. if (textField.styleSheet)
  297. {
  298. // TODO: TextFormat can't be set on a TextField with a StyleSheet, so we need to fix something for this
  299. }
  300. else
  301. {
  302. var textFormat:TextFormat = textField.getTextFormat();
  303. textFormat.font = fontName;
  304. textField.setTextFormat(textFormat);
  305. textField.defaultTextFormat = textFormat;
  306. }
  307. }
  308. /**
  309. * Descreases the fontSize of the TextField till the text has the specified amount of lines.
  310. */
  311. public static function fitToLines(field:TextField, lines:int = 1, affectTextFieldHeight:Boolean = false):void
  312. {
  313. var size:Number = Number(field.getTextFormat().size);
  314. while (field.numLines > lines && size)
  315. {
  316. TextFieldUtils.setFontSize(field, size--);
  317. }
  318. if (affectTextFieldHeight)
  319. {
  320. var lineMetrics:TextLineMetrics = field.getLineMetrics(0);
  321. field.height = lineMetrics.height + 4 + lineMetrics.leading * (lines - 1);
  322. }
  323. }
  324. /**
  325. * @private
  326. */
  327. public static function toString():String
  328. {
  329. return objectToString(TextFieldUtils);
  330. }
  331. }
  332. }