1 /****************************************************************************
  2  Copyright (c) 2011-2012 cocos2d-x.org
  3  Copyright (c) 2013-2014 Chukong Technologies Inc.
  4 
  5  http://www.cocos2d-x.org
  6 
  7  Permission is hereby granted, free of charge, to any person obtaining a copy
  8  of this software and associated documentation files (the "Software"), to deal
  9  in the Software without restriction, including without limitation the rights
 10  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 11  copies of the Software, and to permit persons to whom the Software is
 12  furnished to do so, subject to the following conditions:
 13 
 14  The above copyright notice and this permission notice shall be included in
 15  all copies or substantial portions of the Software.
 16 
 17  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 18  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 19  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 20  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 21  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 22  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 23  THE SOFTWARE.
 24  ****************************************************************************/
 25 
 26 /**
 27  * The text control of Cocos UI.
 28  * @class
 29  * @extends ccui.Widget
 30  *
 31  * @property {Number}   boundingWidth       - Width of the bounding area of label, the real content width is limited by boundingWidth
 32  * @property {Number}   boundingHeight      - Height of the bounding area of label, the real content height is limited by boundingHeight
 33  * @property {String}   string              - The content string of the label
 34  * @property {Number}   stringLength        - <@readonly> The content string length of the label
 35  * @property {String}   font                - The label font with a style string: e.g. "18px Verdana"
 36  * @property {String}   fontName            - The label font name
 37  * @property {Number}   fontSize            - The label font size
 38  * @property {Number}   textAlign           - Horizontal Alignment of label, cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT
 39  * @property {Number}   verticalAlign       - Vertical Alignment of label: cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM
 40  * @property {Boolean}  touchScaleEnabled   - Indicate whether the label will scale when touching
 41  */
 42 ccui.Text = ccui.Widget.extend(/** @lends ccui.Text# */{
 43     _touchScaleChangeEnabled: false,
 44     _normalScaleValueX: 1,
 45     _normalScaleValueY: 1,
 46     _fontName: "Thonburi",
 47     _fontSize: 10,
 48     _onSelectedScaleOffset:0.5,
 49     _labelRenderer: "",
 50     _textAreaSize: null,
 51     _textVerticalAlignment: 0,
 52     _textHorizontalAlignment: 0,
 53     _className: "Text",
 54     _type: null,
 55     _labelRendererAdaptDirty: true,
 56 
 57     /**
 58      * allocates and initializes a UILabel.
 59      * Constructor of ccui.Text. override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.
 60      * @param {String} textContent
 61      * @param {String} fontName
 62      * @param {Number} fontSize
 63      * @example
 64      * // example
 65      * var uiLabel = new ccui.Text();
 66      */
 67     ctor: function (textContent, fontName, fontSize) {
 68         this._type = ccui.Text.Type.SYSTEM;
 69         this._textAreaSize = cc.size(0, 0);
 70         ccui.Widget.prototype.ctor.call(this);
 71 
 72         fontSize !== undefined && this.init(textContent, fontName, fontSize);
 73 
 74     },
 75 
 76     /**
 77      * Initializes a ccui.Text. Please do not call this function by yourself, you should pass the parameters to constructor to initialize it.
 78      * @param {String} textContent
 79      * @param {String} fontName
 80      * @param {Number} fontSize
 81      * @returns {boolean}
 82      * @override
 83      */
 84     init: function (textContent, fontName, fontSize) {
 85         if (ccui.Widget.prototype.init.call(this)) {
 86             if(arguments.length > 0){
 87                 this.setFontName(fontName);
 88                 this.setFontSize(fontSize);
 89                 this.setString(textContent);
 90             }else{
 91                 this.setFontName(this._fontName);
 92             }
 93             return true;
 94         }
 95         return false;
 96     },
 97 
 98     _initRenderer: function () {
 99         this._labelRenderer = new cc.LabelTTF();
100         this.addProtectedChild(this._labelRenderer, ccui.Text.RENDERER_ZORDER, -1);
101     },
102 
103     /**
104      * Changes the  value of ccui.Text.
105      * @deprecated since v3.0, please use setString() instead.
106      * @param {String} text
107      */
108     setText: function (text) {
109         cc.log("Please use the setString");
110         this.setString(text);
111     },
112 
113     /**
114      * Changes the  value of ccui.Text.
115      * @param {String} text
116      */
117     setString: function (text) {
118         if(text === this._labelRenderer.getString())
119             return;
120         this._labelRenderer.setString(text);
121         this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
122         this._labelRendererAdaptDirty = true;
123     },
124 
125     /**
126      * Gets the string value of ccui.Text.
127      * @deprecated since v3.0, please use getString instead.
128      * @returns {String}
129      */
130     getStringValue: function () {
131         cc.log("Please use the getString");
132         return this._labelRenderer.getString();
133     },
134 
135     /**
136      * Gets the string value of ccui.Text.
137      * @returns {String}
138      */
139     getString: function () {
140         return this._labelRenderer.getString();
141     },
142 
143     /**
144      * Gets the string length of ccui.Text.
145      * @returns {Number}
146      */
147     getStringLength: function () {
148         return this._labelRenderer.getStringLength();
149     },
150 
151     /**
152      * Sets fontSize
153      * @param {Number} size
154      */
155     setFontSize: function (size) {
156         this._labelRenderer.setFontSize(size);
157         this._fontSize = size;
158         this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
159         this._labelRendererAdaptDirty = true;
160     },
161 
162     /**
163      * Returns font Size of ccui.Text
164      * @returns {Number}
165      */
166     getFontSize: function () {
167         return this._fontSize;
168     },
169 
170     /**
171      * Sets font name
172      * @return {String} name
173      */
174     setFontName: function (name) {
175         this._fontName = name;
176         this._labelRenderer.setFontName(name);
177         this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
178         this._labelRendererAdaptDirty = true;
179     },
180 
181     /**
182      * Returns font name of ccui.Text.
183      * @returns {string}
184      */
185     getFontName: function () {
186         return this._fontName;
187     },
188 
189     _setFont: function (font) {
190         var res = cc.LabelTTF._fontStyleRE.exec(font);
191         if (res) {
192             this._fontSize = parseInt(res[1]);
193             this._fontName = res[2];
194             this._labelRenderer._setFont(font);
195             this._labelScaleChangedWithSize();
196         }
197     },
198     _getFont: function () {
199         return this._labelRenderer._getFont();
200     },
201 
202     /**
203      * Returns the type of ccui.Text.
204      * @returns {null}
205      */
206     getType: function(){
207         return  this._type;
208     },
209 
210     /**
211      * Sets text Area Size
212      * @param {cc.Size} size
213      */
214     setTextAreaSize: function (size) {
215         this._labelRenderer.setDimensions(size);
216         if (!this._ignoreSize){
217             this._customSize = size;
218         }
219         this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
220         this._labelRendererAdaptDirty = true;
221     },
222 
223     /**
224      * Returns renderer's dimension.
225      * @returns {cc.Size}
226      */
227     getTextAreaSize: function(){
228         return this._labelRenderer.getDimensions();
229     },
230 
231     /**
232      * Sets Horizontal Alignment of cc.LabelTTF
233      * @param {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} alignment Horizontal Alignment
234      */
235     setTextHorizontalAlignment: function (alignment) {
236         this._labelRenderer.setHorizontalAlignment(alignment);
237         this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
238         this._labelRendererAdaptDirty = true;
239     },
240 
241     /**
242      * Returns Horizontal Alignment of label
243      * @returns {TEXT_ALIGNMENT_LEFT|TEXT_ALIGNMENT_CENTER|TEXT_ALIGNMENT_RIGHT}
244      */
245     getTextHorizontalAlignment: function () {
246         return this._labelRenderer.getHorizontalAlignment();
247     },
248 
249     /**
250      * Sets Vertical Alignment of label
251      * @param {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM} alignment
252      */
253     setTextVerticalAlignment: function (alignment) {
254         this._labelRenderer.setVerticalAlignment(alignment);
255         this._updateContentSizeWithTextureSize(this._labelRenderer.getContentSize());
256         this._labelRendererAdaptDirty = true;
257     },
258 
259     /**
260      * Gets text vertical alignment.
261      * @returns {VERTICAL_TEXT_ALIGNMENT_TOP|VERTICAL_TEXT_ALIGNMENT_CENTER|VERTICAL_TEXT_ALIGNMENT_BOTTOM}
262      */
263     getTextVerticalAlignment: function () {
264         return this._labelRenderer.getVerticalAlignment();
265     },
266 
267     /**
268      * Sets the touch scale enabled of label.
269      * @param {Boolean} enable
270      */
271     setTouchScaleChangeEnabled: function (enable) {
272         this._touchScaleChangeEnabled = enable;
273     },
274 
275     /**
276      * Gets the touch scale enabled of label.
277      * @returns {Boolean}
278      */
279     isTouchScaleChangeEnabled: function () {
280         return this._touchScaleChangeEnabled;
281     },
282 
283     _onPressStateChangedToNormal: function () {
284         if (!this._touchScaleChangeEnabled)
285             return;
286         this._labelRenderer.setScaleX(this._normalScaleValueX);
287         this._labelRenderer.setScaleY(this._normalScaleValueY);
288     },
289 
290     _onPressStateChangedToPressed: function () {
291         if (!this._touchScaleChangeEnabled)
292             return;
293         this._labelRenderer.setScaleX(this._normalScaleValueX + this._onSelectedScaleOffset);
294         this._labelRenderer.setScaleY(this._normalScaleValueY + this._onSelectedScaleOffset);
295     },
296 
297     _onPressStateChangedToDisabled: function () {
298     },
299 
300     _onSizeChanged: function () {
301         ccui.Widget.prototype._onSizeChanged.call(this);
302         this._labelRendererAdaptDirty = true;
303     },
304 
305     _adaptRenderers: function(){
306         if (this._labelRendererAdaptDirty) {
307             this._labelScaleChangedWithSize();
308             this._labelRendererAdaptDirty = false;
309         }
310     },
311 
312     /**
313      * Returns the renderer's content size.
314      * @override
315      * @returns {cc.Size}
316      */
317     getVirtualRendererSize: function(){
318         return this._labelRenderer.getContentSize();
319     },
320 
321     /**
322      * Returns the renderer of ccui.Text.
323      * @returns {cc.Node}
324      */
325     getVirtualRenderer: function () {
326         return this._labelRenderer;
327     },
328 
329     //@since v3.3
330     getAutoRenderSize: function(){
331         var virtualSize = this._labelRenderer.getContentSize();
332         if (!this._ignoreSize) {
333             this._labelRenderer.setDimensions(0, 0);
334             virtualSize = this._labelRenderer.getContentSize();
335             this._labelRenderer.setDimensions(this._contentSize.width, this._contentSize.height);
336         }
337         return virtualSize;
338     },
339 
340     _labelScaleChangedWithSize: function () {
341         var locContentSize = this._contentSize;
342         if (this._ignoreSize) {
343             this._labelRenderer.setDimensions(0,0);
344             this._labelRenderer.setScale(1.0);
345             this._normalScaleValueX = this._normalScaleValueY = 1;
346         } else {
347             this._labelRenderer.setDimensions(cc.size(locContentSize.width, locContentSize.height));
348             var textureSize = this._labelRenderer.getContentSize();
349             if (textureSize.width <= 0.0 || textureSize.height <= 0.0) {
350                 this._labelRenderer.setScale(1.0);
351                 return;
352             }
353             var scaleX = locContentSize.width / textureSize.width;
354             var scaleY = locContentSize.height / textureSize.height;
355             this._labelRenderer.setScaleX(scaleX);
356             this._labelRenderer.setScaleY(scaleY);
357             this._normalScaleValueX = scaleX;
358             this._normalScaleValueY = scaleY;
359         }
360         this._labelRenderer.setPosition(locContentSize.width / 2.0, locContentSize.height / 2.0);
361     },
362 
363     /**
364      * Returns the "class name" of ccui.Text.
365      * @returns {string}
366      */
367     getDescription: function () {
368         return "Label";
369     },
370 
371     /**
372      * Enables shadow style and sets color, offset and blur radius styles.
373      * @param {cc.Color} shadowColor
374      * @param {cc.Size} offset
375      * @param {Number} blurRadius
376      */
377     enableShadow: function(shadowColor, offset, blurRadius){
378         this._labelRenderer.enableShadow(shadowColor, offset, blurRadius);
379     },
380 
381     /**
382      * Enables outline style and sets outline's color and size.
383      * @param {cc.Color} outlineColor
384      * @param {cc.Size} outlineSize
385      */
386     enableOutline: function(outlineColor, outlineSize){
387         this._labelRenderer.enableStroke(outlineColor, outlineSize);
388     },
389 
390     /**
391      * Enables glow color
392      * @param glowColor
393      */
394     enableGlow: function(glowColor){
395         if (this._type === ccui.Text.Type.TTF)
396             this._labelRenderer.enableGlow(glowColor);
397     },
398 
399     /**
400      * Disables renderer's effect.
401      */
402     disableEffect: function(){
403         if(this._labelRenderer.disableEffect)
404             this._labelRenderer.disableEffect();
405     },
406 
407     _createCloneInstance: function () {
408         return new ccui.Text();
409     },
410 
411     _copySpecialProperties: function (uiLabel) {
412         if(uiLabel instanceof ccui.Text){
413             this.setFontName(uiLabel._fontName);
414             this.setFontSize(uiLabel.getFontSize());
415             this.setString(uiLabel.getString());
416             this.setTouchScaleChangeEnabled(uiLabel.touchScaleEnabled);
417             this.setTextAreaSize(uiLabel._textAreaSize);
418             this.setTextHorizontalAlignment(uiLabel._labelRenderer.getHorizontalAlignment());
419             this.setTextVerticalAlignment(uiLabel._labelRenderer.getVerticalAlignment());
420             this.setContentSize(uiLabel.getContentSize());
421             this.setTextColor(uiLabel.getTextColor());
422         }
423     },
424 
425     _setBoundingWidth: function (value) {
426         this._textAreaSize.width = value;
427         this._labelRenderer._setBoundingWidth(value);
428         this._labelScaleChangedWithSize();
429     },
430     _setBoundingHeight: function (value) {
431         this._textAreaSize.height = value;
432         this._labelRenderer._setBoundingHeight(value);
433         this._labelScaleChangedWithSize();
434     },
435     _getBoundingWidth: function () {
436         return this._textAreaSize.width;
437     },
438     _getBoundingHeight: function () {
439         return this._textAreaSize.height;
440     },
441 
442     _changePosition: function(){
443         this._adaptRenderers();
444     },
445 
446     setColor: function(color){
447         cc.ProtectedNode.prototype.setColor.call(this, color);
448         this._labelRenderer.setColor(color);
449     },
450 
451     setTextColor: function(color){
452         this._labelRenderer.setFontFillColor(color);
453     },
454 
455     getTextColor: function(){
456         return this._labelRenderer._getFillStyle();
457     }
458 });
459 
460 var _p = ccui.Text.prototype;
461 
462 // Extended properties
463 /** @expose */
464 _p.boundingWidth;
465 cc.defineGetterSetter(_p, "boundingWidth", _p._getBoundingWidth, _p._setBoundingWidth);
466 /** @expose */
467 _p.boundingHeight;
468 cc.defineGetterSetter(_p, "boundingHeight", _p._getBoundingHeight, _p._setBoundingHeight);
469 /** @expose */
470 _p.string;
471 cc.defineGetterSetter(_p, "string", _p.getString, _p.setString);
472 /** @expose */
473 _p.stringLength;
474 cc.defineGetterSetter(_p, "stringLength", _p.getStringLength);
475 /** @expose */
476 _p.font;
477 cc.defineGetterSetter(_p, "font", _p._getFont, _p._setFont);
478 /** @expose */
479 _p.fontSize;
480 cc.defineGetterSetter(_p, "fontSize", _p.getFontSize, _p.setFontSize);
481 /** @expose */
482 _p.fontName;
483 cc.defineGetterSetter(_p, "fontName", _p.getFontName, _p.setFontName);
484 /** @expose */
485 _p.textAlign;
486 cc.defineGetterSetter(_p, "textAlign", _p.getTextHorizontalAlignment, _p.setTextHorizontalAlignment);
487 /** @expose */
488 _p.verticalAlign;
489 cc.defineGetterSetter(_p, "verticalAlign", _p.getTextVerticalAlignment, _p.setTextVerticalAlignment);
490 
491 _p = null;
492 
493 /**
494  * allocates and initializes a UILabel.
495  * @deprecated since v3.0, please use new ccui.Text() instead.
496  * @return {ccui.Text}
497  */
498 ccui.Label = ccui.Text.create = function (textContent, fontName, fontSize) {
499     return new ccui.Text(textContent, fontName, fontSize);
500 };
501 
502 /**
503  * The zOrder value of ccui.Text's renderer.
504  * @constant
505  * @type {number}
506  */
507 ccui.Text.RENDERER_ZORDER = -1;
508 
509 /**
510  * @ignore
511  */
512 ccui.Text.Type = {
513     SYSTEM: 0,
514     TTF: 1
515 };