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         }
422     },
423 
424     _setBoundingWidth: function (value) {
425         this._textAreaSize.width = value;
426         this._labelRenderer._setBoundingWidth(value);
427         this._labelScaleChangedWithSize();
428     },
429     _setBoundingHeight: function (value) {
430         this._textAreaSize.height = value;
431         this._labelRenderer._setBoundingHeight(value);
432         this._labelScaleChangedWithSize();
433     },
434     _getBoundingWidth: function () {
435         return this._textAreaSize.width;
436     },
437     _getBoundingHeight: function () {
438         return this._textAreaSize.height;
439     },
440 
441     _changePosition: function(){
442         this._adaptRenderers();
443     },
444 
445     setColor: function(color){
446         cc.ProtectedNode.prototype.setColor.call(this, color);
447         this._labelRenderer.setColor(color);
448     },
449 
450     setTextColor: function(color){
451         this._labelRenderer.setFontFillColor(color);
452     },
453 
454     getTextColor: function(){
455         return this._labelRenderer._getFillStyle();
456     }
457 });
458 
459 var _p = ccui.Text.prototype;
460 
461 // Extended properties
462 /** @expose */
463 _p.boundingWidth;
464 cc.defineGetterSetter(_p, "boundingWidth", _p._getBoundingWidth, _p._setBoundingWidth);
465 /** @expose */
466 _p.boundingHeight;
467 cc.defineGetterSetter(_p, "boundingHeight", _p._getBoundingHeight, _p._setBoundingHeight);
468 /** @expose */
469 _p.string;
470 cc.defineGetterSetter(_p, "string", _p.getString, _p.setString);
471 /** @expose */
472 _p.stringLength;
473 cc.defineGetterSetter(_p, "stringLength", _p.getStringLength);
474 /** @expose */
475 _p.font;
476 cc.defineGetterSetter(_p, "font", _p._getFont, _p._setFont);
477 /** @expose */
478 _p.fontSize;
479 cc.defineGetterSetter(_p, "fontSize", _p.getFontSize, _p.setFontSize);
480 /** @expose */
481 _p.fontName;
482 cc.defineGetterSetter(_p, "fontName", _p.getFontName, _p.setFontName);
483 /** @expose */
484 _p.textAlign;
485 cc.defineGetterSetter(_p, "textAlign", _p.getTextHorizontalAlignment, _p.setTextHorizontalAlignment);
486 /** @expose */
487 _p.verticalAlign;
488 cc.defineGetterSetter(_p, "verticalAlign", _p.getTextVerticalAlignment, _p.setTextVerticalAlignment);
489 
490 _p = null;
491 
492 /**
493  * allocates and initializes a UILabel.
494  * @deprecated since v3.0, please use new ccui.Text() instead.
495  * @return {ccui.Text}
496  */
497 ccui.Label = ccui.Text.create = function (textContent, fontName, fontSize) {
498     return new ccui.Text(textContent, fontName, fontSize);
499 };
500 
501 /**
502  * The zOrder value of ccui.Text's renderer.
503  * @constant
504  * @type {number}
505  */
506 ccui.Text.RENDERER_ZORDER = -1;
507 
508 /**
509  * @ignore
510  */
511 ccui.Text.Type = {
512     SYSTEM: 0,
513     TTF: 1
514 };