1//////////////////////////////////////////////////////////////////////////////// 2// 3// ADOBE SYSTEMS INCORPORATED 4// Copyright 2005-2007 Adobe Systems Incorporated 5// All Rights Reserved. 6// 7// NOTICE: Adobe permits you to use, modify, and distribute this file 8// in accordance with the terms of the license agreement accompanying it. 9// 10//////////////////////////////////////////////////////////////////////////////// 11 12package mx.controls.textClasses 13{ 14 15import flash.text.TextField; 16import flash.text.TextFormat; 17import mx.core.UIComponent; 18import mx.core.mx_internal; 19import mx.styles.StyleManager; 20import mx.utils.StringUtil; 21 22use namespace mx_internal; 23 24/** 25 * The TextRange class provides properties that select and format a range of 26 * text in the Label, Text, TextArea, TextEditor, and RichTextEditor controls. 27 * 28 * @see mx.controls.Label 29 * @see mx.controls.RichTextEditor 30 * @see mx.controls.Text 31 * @see mx.controls.TextArea 32 * @see mx.controls.TextInput 33 * @see flash.text.TextFormatAlign 34 * 35 * @langversion 3.0 36 * @playerversion Flash 9 37 * @playerversion AIR 1.1 38 * @productversion Flex 3 39 */ 40public class TextRange 41{ 42 include "../../core/Version.as"; 43 44 //-------------------------------------------------------------------------- 45 // 46 // Class variables 47 // 48 //-------------------------------------------------------------------------- 49 50 /** 51 * @private 52 */ 53 private static var htmlTextField:TextField; 54 55 //-------------------------------------------------------------------------- 56 // 57 // Constructor 58 // 59 //-------------------------------------------------------------------------- 60 61 /** 62 * Create a new TextRange Object that represents a subset of the contents 63 * of a text control, including the formatting information. 64 * 65 * @param owner The control that contains the text. The control must have 66 * a <code>textField</code> property, or, as is the case of the 67 * RichTextEditor control, a <code>textArea</code> property. 68 * 69 * @param modifiesSelection Whether to select the text in the range. 70 * If you set this parameter to <code>true</code> and do not specify a 71 * begin or end index that corresponds to text in the control, Flex 72 * uses the begin or end index of the current text selection. 73 * If this parameter is <code>true</code>, you omit the 74 * <code>beginIndex</code> and <code>endIndex</code> 75 * parameters, and there is no selection, the TextRange object is empty. 76 * 77 * @param beginIndex Zero-based index of the first character in the range. 78 * If the <code>modifiesSelection</code> parameter is <code>false</code> 79 * and you omit this parameter or specify a negative value, 80 * the range starts with the first text character. 81 * 82 * @param endIndex Zero-based index of the position <i>after</i> the 83 * last character in the range. 84 * If the <code>modifiesSelection</code> parameter is <code>false</code> 85 * and you omit this parameter, specify a negative value, or specify 86 * a value past the end of the text, the range ends with the last 87 * text character. 88 * 89 * @langversion 3.0 90 * @playerversion Flash 9 91 * @playerversion AIR 1.1 92 * @productversion Flex 3 93 */ 94 public function TextRange(owner:UIComponent, 95 modifiesSelection:Boolean = false, 96 beginIndex:int = -1, endIndex:int = -1) 97 { 98 super(); 99 100 _owner = owner; 101 102 try 103 { 104 textField = _owner["textArea"].getTextField(); 105 } 106 catch(e:Error) 107 { 108 textField = this["_owner"].getTextField(); 109 } 110 111 _modifiesSelection = modifiesSelection; 112 113 if (!_modifiesSelection) 114 { 115 if (beginIndex < 0) 116 beginIndex = 0; 117 118 if (beginIndex > textField.length) 119 beginIndex = textField.length; 120 121 if (endIndex < 0 || endIndex > textField.length) 122 endIndex = textField.length; 123 124 _beginIndex = beginIndex; 125 _endIndex = endIndex; 126 } 127 else 128 { 129 if (beginIndex < 0 || beginIndex > textField.length) 130 beginIndex = textField.selectionBeginIndex; 131 132 if (endIndex < 0 || endIndex > textField.length) 133 endIndex = textField.selectionEndIndex; 134 135 textField.selectable = true; 136 137 if (beginIndex != textField.selectionBeginIndex || 138 endIndex != textField.selectionEndIndex) 139 { 140 textField.setSelection(beginIndex, endIndex); 141 } 142 } 143 } 144 145 //-------------------------------------------------------------------------- 146 // 147 // Variables 148 // 149 //-------------------------------------------------------------------------- 150 151 /** 152 * @private 153 */ 154 private var textField:TextField; 155 156 //-------------------------------------------------------------------------- 157 // 158 // Properties 159 // 160 //-------------------------------------------------------------------------- 161 162 //---------------------------------- 163 // beginIndex 164 //---------------------------------- 165 166 /** 167 * Storage for the beginIndex property. 168 * 169 * @langversion 3.0 170 * @playerversion Flash 9 171 * @playerversion AIR 1.1 172 * @productversion Flex 3 173 */ 174 private var _beginIndex:int; 175 176 /** 177 * Zero-based index in the control's text field of the first 178 * character in the range. 179 * If the fifth character in the text is the first character in the 180 * range, this property has a value of 4. 181 * 182 * @langversion 3.0 183 * @playerversion Flash 9 184 * @playerversion AIR 1.1 185 * @productversion Flex 3 186 */ 187 public function get beginIndex():int 188 { 189 if (_modifiesSelection) 190 return textField.selectionBeginIndex; 191 else 192 return _beginIndex; 193 } 194 195 /** 196 * @private 197 */ 198 public function set beginIndex(value:int):void 199 { 200 if (_modifiesSelection) 201 textField.setSelection(value, textField.selectionEndIndex); 202 else 203 _beginIndex = value; 204 } 205 206 //---------------------------------- 207 // bullet 208 //---------------------------------- 209 210 /** 211 * Whether the text in the range is in a bulleted list. 212 * If only part of the range is in a bulleted list, 213 * this value is <code>false</code>. 214 * 215 * @langversion 3.0 216 * @playerversion Flash 9 217 * @playerversion AIR 1.1 218 * @productversion Flex 3 219 */ 220 public function get bullet():Boolean 221 { 222 return getTextFormat().bullet; 223 } 224 225 /** 226 * @private 227 */ 228 public function set bullet(value:Boolean):void 229 { 230 var tf:TextFormat = getTextFormat(); 231 tf.bullet = value; 232 setTextFormat(tf); 233 } 234 235 //---------------------------------- 236 // color 237 //---------------------------------- 238 239 /** 240 * Color of the text in the range. 241 * You can set this value using any valid color identifier. 242 * The property returns the value as a numeric value. 243 * If the range has multiple colors, this value is <code>null</code>. 244 * 245 * @langversion 3.0 246 * @playerversion Flash 9 247 * @playerversion AIR 1.1 248 * @productversion Flex 3 249 */ 250 public function get color():Object 251 { 252 return getTextFormat().color; 253 } 254 255 /** 256 * @private 257 */ 258 public function set color(value:Object):void 259 { 260 var tf:TextFormat = getTextFormat(); 261 var colorNumber:uint = owner.styleManager.getColorName(value); 262 if (colorNumber != StyleManager.NOT_A_COLOR) 263 value = colorNumber; 264 else 265 value = 0; 266 tf.color = value; 267 setTextFormat(tf); 268 } 269 270 //---------------------------------- 271 // endIndex 272 //---------------------------------- 273 274 /** 275 * Storage for the beginIndex property. 276 * 277 * @langversion 3.0 278 * @playerversion Flash 9 279 * @playerversion AIR 1.1 280 * @productversion Flex 3 281 */ 282 private var _endIndex:int; 283 284 /** 285 * Zero-based index in the control's text field of the point 286 * immediately after the last character in the range; equivalent to 287 * the One-based index of the last character. 288 * If the fifth character in the text is the last character in the 289 * range, this property has a value of 5. 290 * 291 * @langversion 3.0 292 * @playerversion Flash 9 293 * @playerversion AIR 1.1 294 * @productversion Flex 3 295 */ 296 public function get endIndex():int 297 { 298 if (_modifiesSelection) 299 return textField.selectionEndIndex; 300 else 301 return _endIndex; 302 } 303 304 /** 305 * @private 306 */ 307 public function set endIndex(value:int):void 308 { 309 if (_modifiesSelection) 310 textField.setSelection(textField.selectionBeginIndex, value); 311 else 312 _endIndex = value; 313 } 314 315 //---------------------------------- 316 // fontFamily 317 //---------------------------------- 318 319 /** 320 * Name of the font for text in the range. 321 * If the range has multiple fonts, this value is <code>null</code>. 322 * 323 * @langversion 3.0 324 * @playerversion Flash 9 325 * @playerversion AIR 1.1 326 * @productversion Flex 3 327 */ 328 public function get fontFamily():String 329 { 330 return getTextFormat().font; 331 } 332 333 /** 334 * @private 335 */ 336 public function set fontFamily(value:String):void 337 { 338 var tf:TextFormat = getTextFormat(); 339 tf.font = StringUtil.trimArrayElements(value,","); 340 setTextFormat(tf); 341 } 342 343 //---------------------------------- 344 // fontSize 345 //---------------------------------- 346 347 /** 348 * Point size of the text in the range. 349 * If the range has multiple sizes, this value is 0. 350 * 351 * @langversion 3.0 352 * @playerversion Flash 9 353 * @playerversion AIR 1.1 354 * @productversion Flex 3 355 */ 356 public function get fontSize():int 357 { 358 return int(getTextFormat().size); 359 } 360 361 /** 362 * @private 363 */ 364 public function set fontSize(value:int):void 365 { 366 var tf:TextFormat = getTextFormat(); 367 tf.size = value; 368 setTextFormat(tf); 369 } 370 371 //---------------------------------- 372 // fontStyle 373 //---------------------------------- 374 375 /** 376 * Style of the font in the range, as "italic" 377 * or "normal". Setting the property to any other string results 378 * in normal style. 379 * If the range has multiple styles, this value is <code>null</code>. 380 * 381 * @langversion 3.0 382 * @playerversion Flash 9 383 * @playerversion AIR 1.1 384 * @productversion Flex 3 385 */ 386 public function get fontStyle():String 387 { 388 return getTextFormat().italic ? "italic" : "normal"; 389 } 390 391 /** 392 * @private 393 */ 394 public function set fontStyle(value:String):void 395 { 396 var tf:TextFormat = getTextFormat(); 397 tf.italic = (value == "italic") ? true : false; 398 setTextFormat(tf); 399 } 400 401 //---------------------------------- 402 // fontWeight 403 //---------------------------------- 404 405 /** 406 * Weight of the font in the range, as "bold" 407 * or "normal". Setting the property to any other string results 408 * in normal weight. 409 * If the range has multiple weights, this value is <code>null</code>. 410 * 411 * @langversion 3.0 412 * @playerversion Flash 9 413 * @playerversion AIR 1.1 414 * @productversion Flex 3 415 */ 416 public function get fontWeight():String 417 { 418 return getTextFormat().bold ? "bold" : "normal"; 419 } 420 421 /** 422 * @private 423 */ 424 public function set fontWeight(value:String):void 425 { 426 var tf:TextFormat = getTextFormat(); 427 tf.bold = (value == "bold") ? true : false; 428 setTextFormat(tf); 429 } 430 431 //---------------------------------- 432 // htmlText 433 //---------------------------------- 434 435 /** 436 * Contents of the range in the form of HTML text. 437 * This property returns all HTML markup for the range, including 438 * markup for formatting that is applied by Flex, not just 439 * HTML that you specify in using an <code>htmlText</code> property. 440 * This property is, therefore, a full HTML representation of the 441 * text as it appears in the control. 442 * 443 * @langversion 3.0 444 * @playerversion Flash 9 445 * @playerversion AIR 1.1 446 * @productversion Flex 3 447 */ 448 public function get htmlText():String 449 { 450 if (beginIndex == endIndex) 451 return ""; 452 453 if (!htmlTextField) 454 { 455 htmlTextField = new TextField(); 456 htmlTextField.multiline = true; 457 } 458 459 htmlTextField.defaultTextFormat = textField.defaultTextFormat; 460 htmlTextField.htmlText = ""; 461 462 htmlTextField.insertXMLText( 463 0, 0, textField.getXMLText(beginIndex, endIndex)) 464 465 return htmlTextField.htmlText; 466 } 467 468 /** 469 * @private 470 */ 471 public function set htmlText(value:String):void 472 { 473 474 if (!htmlTextField) 475 { 476 htmlTextField = new TextField(); 477 htmlTextField.multiline = true; 478 } 479 480 htmlTextField.defaultTextFormat = textField.defaultTextFormat; 481 htmlTextField.htmlText = value; 482 var length:int = htmlTextField.length; 483 484 var oldBeginIndex:int = beginIndex; 485 textField.insertXMLText( 486 beginIndex, endIndex, htmlTextField.getXMLText()); 487 // workaround for what seems to be a player bug (#207147) 488 // where a zero length selection is shifted 489 // (if no bug, this code should never execute) 490 if ((oldBeginIndex == 0) && (beginIndex > 0)) 491 beginIndex = 0; 492 493 endIndex = beginIndex + length; 494 } 495 496 //---------------------------------- 497 // kerning 498 //---------------------------------- 499 500 /** 501 * A Boolean value that indicates whether kerning 502 * is enabled (<code>true</code>) or disabled (<code>false</code>). 503 * Kerning adjusts the pixels between certain character pairs 504 * to improve readability, and should be used only when necessary, 505 * such as with headings in large fonts. 506 * Kerning is supported for embedded fonts only. 507 * Certain fonts, such as Verdana, and monospaced fonts, 508 * such as Courier New, do not support kerning. 509 * 510 * @default false 511 * 512 * @langversion 3.0 513 * @playerversion Flash 9 514 * @playerversion AIR 1.1 515 * @productversion Flex 3 516 */ 517 public function get kerning():Boolean 518 { 519 return Boolean(getTextFormat().kerning); 520 } 521 522 /** 523 * @private 524 */ 525 public function set kerning(value:Boolean):void 526 { 527 var tf:TextFormat = getTextFormat(); 528 tf.kerning = value; 529 setTextFormat(tf); 530 } 531 532 //---------------------------------- 533 // letterSpacing 534 //---------------------------------- 535 536 /** 537 * The number of additional pixels to appear between each character. 538 * A positive value increases the character spacing 539 * beyond the normal spacing, while a negative value decreases it. 540 * 541 * @default 0 542 * 543 * @langversion 3.0 544 * @playerversion Flash 9 545 * @playerversion AIR 1.1 546 * @productversion Flex 3 547 */ 548 public function get letterSpacing():Number 549 { 550 return Number(getTextFormat().letterSpacing); 551 } 552 553 /** 554 * @private 555 */ 556 public function set letterSpacing(value:Number):void 557 { 558 var tf:TextFormat = getTextFormat(); 559 tf.letterSpacing = value; 560 setTextFormat(tf); 561 } 562 563 //---------------------------------- 564 // modifiesSelection 565 //---------------------------------- 566 567 /** 568 * @private 569 * Storage for the modifiesSelection property. 570 */ 571 private var _modifiesSelection:Boolean; 572 573 /** 574 * Whether the TextRange modifies the currenly selected text. 575 * Set by the constructor. 576 * 577 * @langversion 3.0 578 * @playerversion Flash 9 579 * @playerversion AIR 1.1 580 * @productversion Flex 3 581 */ 582 public function get modifiesSelection():Boolean 583 { 584 return _modifiesSelection; 585 } 586 587 //---------------------------------- 588 // owner 589 //---------------------------------- 590 591 /** 592 * @private 593 * Storage for the owner property. 594 */ 595 private var _owner:UIComponent; 596 597 /** 598 * The control that contains the text. 599 * The owner control must have a <code>textField</code> property, 600 * or, as is the case of the RichTextEditor control, 601 * a <code>textArea</code> property. 602 * The owner of the text in a RichTextEditor control is the 603 * RichTextEditor control, not its TextArea subcontrol. 604 * Initially set by the constructor. 605 * 606 * @langversion 3.0 607 * @playerversion Flash 9 608 * @playerversion AIR 1.1 609 * @productversion Flex 3 610 */ 611 public function get owner():UIComponent 612 { 613 return _owner; 614 } 615 616 /** 617 * @private 618 */ 619 public function set owner(value:UIComponent):void 620 { 621 _owner = value; 622 623 try 624 { 625 textField = _owner["textArea"]["textField"]; 626 } 627 catch(e:Error) 628 { 629 textField = _owner["textField"]; 630 } 631 } 632 633 //---------------------------------- 634 // text 635 //---------------------------------- 636 637 /** 638 * Plain-text contents of the range. 639 * 640 * @langversion 3.0 641 * @playerversion Flash 9 642 * @playerversion AIR 1.1 643 * @productversion Flex 3 644 */ 645 public function get text():String 646 { 647 return textField.text.substring(beginIndex, endIndex); 648 } 649 650 /** 651 * @private 652 */ 653 public function set text(value:String):void 654 { 655 var oldBeginIndex:int = beginIndex; 656 textField.replaceText(beginIndex,endIndex,value); 657 // workaround for what seems to be a player bug (#207147) 658 // where a zero length selection is shifted 659 // (if no bug, this code should never execute) 660 if ((oldBeginIndex == 0) && (beginIndex > 0)) 661 beginIndex = 0; 662 endIndex = beginIndex + value.length; 663 } 664 665 //---------------------------------- 666 // textAlign 667 //---------------------------------- 668 669 /** 670 * Alignment of the text in the range. 671 * The flash.text.TextFormatAlign constants specify the valid values. 672 * Setting this property to any other value has no effect. 673 * If the range has multiple alignments, this value is <code>null</code>. 674 * 675 * @see flash.text.TextFormatAlign 676 * 677 * @langversion 3.0 678 * @playerversion Flash 9 679 * @playerversion AIR 1.1 680 * @productversion Flex 3 681 */ 682 public function get textAlign():String 683 { 684 return getTextFormat().align; 685 } 686 687 /** 688 * @private 689 */ 690 public function set textAlign(value:String):void 691 { 692 var tf:TextFormat = getTextFormat(); 693 tf.align = value; 694 setTextFormat(tf); 695 } 696 697 //---------------------------------- 698 // textDecoration 699 //---------------------------------- 700 701 /** 702 * Decoration of the font in the range, as "underline" 703 * or "normal". Setting the property to any other string results 704 * in normal text. 705 * If the range has multiple decoration settings, this value is 706 * <code>null</code>. 707 * 708 * @langversion 3.0 709 * @playerversion Flash 9 710 * @playerversion AIR 1.1 711 * @productversion Flex 3 712 */ 713 public function get textDecoration():String 714 { 715 return getTextFormat().underline ? "underline" : "normal"; 716 } 717 718 /** 719 * @private 720 */ 721 public function set textDecoration(value:String):void 722 { 723 var tf:TextFormat = getTextFormat(); 724 tf.underline = (value == "underline") ? true : false; 725 setTextFormat(tf); 726 } 727 728 //---------------------------------- 729 // url 730 //---------------------------------- 731 732 /** 733 * URL for a hypertext link in the range. 734 * If the range does not include a link, the value 735 * is the empty string. 736 * If the range includes multiple links, the value 737 * is <code>null</code>. 738 * 739 * @langversion 3.0 740 * @playerversion Flash 9 741 * @playerversion AIR 1.1 742 * @productversion Flex 3 743 */ 744 public function get url():String 745 { 746 return getTextFormat().url; 747 } 748 749 /** 750 * @private 751 */ 752 public function set url(value:String):void 753 { 754 var tf:TextFormat = getTextFormat(); 755 756 if (value != "") 757 { 758 tf.url = value; 759 tf.target = "_blank"; 760 } 761 else if (tf.url != "") 762 { 763 tf.url = ""; 764 tf.target = ""; 765 } 766 767 setTextFormat(tf); 768 } 769 770 //-------------------------------------------------------------------------- 771 // 772 // Methods 773 // 774 //-------------------------------------------------------------------------- 775 776 /** 777 * @private 778 */ 779 private function getTextFormat():TextFormat 780 { 781 var tf:TextFormat; 782 if (_modifiesSelection && beginIndex == endIndex) 783 tf = textField.defaultTextFormat; 784 else 785 tf = textField.getTextFormat(beginIndex, endIndex); 786 return tf; 787 } 788 789 /** 790 * @private 791 */ 792 private function setTextFormat(tf:TextFormat):void 793 { 794 if (_modifiesSelection && beginIndex == endIndex) 795 textField.defaultTextFormat = tf; 796 else 797 textField.setTextFormat(tf,beginIndex, endIndex); 798 } 799} 800 801}