1
- import { fontInternalProperty , Length , paddingBottomProperty , paddingLeftProperty , paddingRightProperty , paddingTopProperty , View } from 'tns-core-modules/ui/page/page' ;
1
+ import { fontInternalProperty , Length , paddingBottomProperty , paddingLeftProperty , paddingRightProperty , paddingTopProperty , View , colorProperty , Color } from 'tns-core-modules/ui/page/page' ;
2
2
import { Font } from 'tns-core-modules/ui/styling/font' ;
3
- import { borderBottomWidthProperty , borderLeftWidthProperty , borderRightWidthProperty , borderTopWidthProperty , TextTransform , WhiteSpace , whiteSpaceProperty } from 'tns-core-modules/ui/text-base/text-base' ;
3
+ import {
4
+ borderBottomWidthProperty ,
5
+ borderLeftWidthProperty ,
6
+ borderRightWidthProperty ,
7
+ borderTopWidthProperty ,
8
+ TextTransform ,
9
+ WhiteSpace ,
10
+ whiteSpaceProperty ,
11
+ formattedTextProperty ,
12
+ FormattedString
13
+ } from 'tns-core-modules/ui/text-base/text-base' ;
4
14
import { isString } from 'tns-core-modules/utils/types' ;
5
15
import { layout } from 'tns-core-modules/utils/utils' ;
6
16
import { TextShadow , VerticalTextAlignment , verticalTextAlignmentProperty } from './label' ;
@@ -81,15 +91,14 @@ export class Label extends LabelBase {
81
91
private _observer : NSObject ;
82
92
nativeViewProtected : UITextView ;
83
93
nativeTextViewProtected : UITextView ;
84
- static DTCORETEXT_INIT = false ;
94
+ // static DTCORETEXT_INIT = false;
85
95
constructor ( ) {
86
96
super ( ) ;
87
- if ( ! Label . DTCORETEXT_INIT ) {
88
- Label . DTCORETEXT_INIT = true ;
89
- DTCoreTextFontDescriptor . asyncPreloadFontLookupTable ( ) ;
90
- }
97
+ // if (!Label.DTCORETEXT_INIT) {
98
+ // Label.DTCORETEXT_INIT = true;
99
+ // DTCoreTextFontDescriptor.asyncPreloadFontLookupTable();
100
+ // }
91
101
}
92
-
93
102
public createNativeView ( ) {
94
103
const view = UITextView . new ( ) ;
95
104
if ( ! view . font ) {
@@ -130,7 +139,16 @@ export class Label extends LabelBase {
130
139
this . _observer = null ;
131
140
}
132
141
}
133
-
142
+ computeTextHeight ( size : CGSize ) {
143
+ const tv = this . nativeTextViewProtected ;
144
+ const font = this . nativeViewProtected . font ;
145
+ const text = this . formattedText || this . html ? tv . attributedText : tv . text ;
146
+ if ( text instanceof NSAttributedString ) {
147
+ const rect = text . boundingRectWithSizeOptionsContext ( size , NSStringDrawingOptions . UsesLineFragmentOrigin , null ) ;
148
+ return rect . size . height ;
149
+ }
150
+ return NSString . stringWithString ( text ) . sizeWithFontConstrainedToSizeLineBreakMode ( font , size , tv . textContainer . lineBreakMode ) . height ;
151
+ }
134
152
updateVerticalAlignment ( ) {
135
153
const tv = this . nativeTextViewProtected ;
136
154
const inset = this . nativeViewProtected . textContainerInset ;
@@ -148,7 +166,7 @@ export class Label extends LabelBase {
148
166
149
167
case 'middle' :
150
168
case 'center' : {
151
- const height = tv . sizeThatFits ( CGSizeMake ( tv . bounds . size . width , 10000 ) ) . height ;
169
+ const height = this . computeTextHeight ( CGSizeMake ( tv . bounds . size . width , 10000 ) ) ;
152
170
let topCorrect = ( tv . bounds . size . height - height * tv . zoomScale ) / 2.0 ;
153
171
topCorrect = topCorrect < 0.0 ? 0.0 : topCorrect ;
154
172
// tv.contentOffset = CGPointMake(0, -topCorrect);
@@ -162,7 +180,7 @@ export class Label extends LabelBase {
162
180
}
163
181
164
182
case 'bottom' : {
165
- const height = tv . sizeThatFits ( CGSizeMake ( tv . bounds . size . width , 10000 ) ) . height ;
183
+ const height = this . computeTextHeight ( CGSizeMake ( tv . bounds . size . width , 10000 ) ) ;
166
184
let bottomCorrect = tv . bounds . size . height - height * tv . zoomScale ;
167
185
bottomCorrect = bottomCorrect < 0.0 ? 0.0 : bottomCorrect ;
168
186
// tv.contentOffset = CGPointMake(0, -bottomCorrect);
@@ -182,86 +200,86 @@ export class Label extends LabelBase {
182
200
}
183
201
private _fixedSize : FixedSize ;
184
202
185
- setTextDecorationAndTransform ( ) {
186
- const style = this . style ;
187
- const dict = new Map < string , any > ( ) ;
188
- switch ( style . textDecoration ) {
189
- case 'none' :
190
- break ;
191
- case 'underline' :
192
- // TODO: Replace deprecated `StyleSingle` with `Single` after the next typings update
193
- dict . set ( NSUnderlineStyleAttributeName , NSUnderlineStyle . Single ) ;
194
- break ;
195
- case 'line-through' :
196
- // TODO: Replace deprecated `StyleSingle` with `Single` after the next typings update
197
- dict . set ( NSStrikethroughStyleAttributeName , NSUnderlineStyle . Single ) ;
198
- break ;
199
- case 'underline line-through' :
200
- // TODO: Replace deprecated `StyleSingle` with `Single` after the next typings update
201
- dict . set ( NSUnderlineStyleAttributeName , NSUnderlineStyle . Single ) ;
202
- dict . set ( NSStrikethroughStyleAttributeName , NSUnderlineStyle . Single ) ;
203
- break ;
204
- default :
205
- throw new Error ( `Invalid text decoration value: ${ style . textDecoration } . Valid values are: 'none', 'underline', 'line-through', 'underline line-through'.` ) ;
206
- }
207
-
208
- if ( style . letterSpacing !== 0 ) {
209
- dict . set ( NSKernAttributeName , style . letterSpacing * this . nativeTextViewProtected . font . pointSize ) ;
210
- }
211
-
212
- const isTextView = this . nativeTextViewProtected instanceof UITextView ;
213
- if ( style . lineHeight || style . whiteSpace === 'nowrap' || ( style [ 'lineBreak' ] && style [ 'lineBreak' ] !== 'none' ) ) {
214
- const paragraphStyle = NSMutableParagraphStyle . alloc ( ) . init ( ) ;
215
- paragraphStyle . minimumLineHeight = style . lineHeight ;
216
- // make sure a possible previously set text alignment setting is not lost when line height is specified
217
- paragraphStyle . alignment = ( this . nativeTextViewProtected as UITextField | UITextView | UILabel ) . textAlignment ;
218
-
219
- // make sure a possible previously set line break mode is not lost when line height is specified
203
+ // setTextDecorationAndTransform() {
204
+ // const style = this.style;
205
+ // const dict = new Map<string, any>();
206
+ // switch (style.textDecoration) {
207
+ // case 'none':
208
+ // break;
209
+ // case 'underline':
210
+ // // TODO: Replace deprecated `StyleSingle` with `Single` after the next typings update
211
+ // dict.set(NSUnderlineStyleAttributeName, NSUnderlineStyle.Single);
212
+ // break;
213
+ // case 'line-through':
214
+ // // TODO: Replace deprecated `StyleSingle` with `Single` after the next typings update
215
+ // dict.set(NSStrikethroughStyleAttributeName, NSUnderlineStyle.Single);
216
+ // break;
217
+ // case 'underline line-through':
218
+ // // TODO: Replace deprecated `StyleSingle` with `Single` after the next typings update
219
+ // dict.set(NSUnderlineStyleAttributeName, NSUnderlineStyle.Single);
220
+ // dict.set(NSStrikethroughStyleAttributeName, NSUnderlineStyle.Single);
221
+ // break;
222
+ // default:
223
+ // throw new Error(`Invalid text decoration value: ${style.textDecoration}. Valid values are: 'none', 'underline', 'line-through', 'underline line-through'.`);
224
+ // }
220
225
221
- if ( style [ 'lineBreak' ] ) {
222
- paragraphStyle . lineBreakMode = lineBreakToLineBreakMode ( style [ 'lineBreak' ] ) ;
223
- } else if ( style . whiteSpace ) {
224
- paragraphStyle . lineBreakMode = whiteSpaceToLineBreakMode ( style . whiteSpace ) ;
225
- }
226
- dict . set ( NSParagraphStyleAttributeName , paragraphStyle ) ;
227
- } else if ( isTextView && this . style . textAlignment !== 'initial' ) {
228
- const paragraphStyle = NSMutableParagraphStyle . alloc ( ) . init ( ) ;
229
- paragraphStyle . alignment = this . nativeTextViewProtected . textAlignment ;
230
- dict . set ( NSParagraphStyleAttributeName , paragraphStyle ) ;
231
- }
226
+ // if (style.letterSpacing !== 0) {
227
+ // dict.set(NSKernAttributeName, style.letterSpacing * this.nativeTextViewProtected.font.pointSize);
228
+ // }
232
229
233
- if ( style . color && dict . size > 0 ) {
234
- dict . set ( NSForegroundColorAttributeName , style . color . ios ) ;
235
- }
230
+ // if (style.lineHeight || style.whiteSpace === 'nowrap' || (style['lineBreak'] && style['lineBreak'] !== 'none')) {
231
+ // const paragraphStyle = NSMutableParagraphStyle.alloc().init();
232
+ // paragraphStyle.minimumLineHeight = style.lineHeight;
233
+ // // make sure a possible previously set text alignment setting is not lost when line height is specified
234
+ // paragraphStyle.alignment = (this.nativeTextViewProtected as UITextField | UITextView | UILabel).textAlignment;
235
+
236
+ // // make sure a possible previously set line break mode is not lost when line height is specified
237
+
238
+ // if (style['lineBreak']) {
239
+ // paragraphStyle.lineBreakMode = lineBreakToLineBreakMode(style['lineBreak']);
240
+ // } else if (style.whiteSpace) {
241
+ // paragraphStyle.lineBreakMode = whiteSpaceToLineBreakMode(style.whiteSpace);
242
+ // }
243
+ // dict.set(NSParagraphStyleAttributeName, paragraphStyle);
244
+ // } else if (isTextView && this.style.textAlignment !== 'initial') {
245
+ // const paragraphStyle = NSMutableParagraphStyle.alloc().init();
246
+ // paragraphStyle.alignment = this.nativeTextViewProtected.textAlignment;
247
+ // dict.set(NSParagraphStyleAttributeName, paragraphStyle);
248
+ // }
236
249
237
- const text = this . text ;
238
- const str = text === undefined || text === null ? '' : text . toString ( ) ;
239
- const source = getTransformedText ( str , this . textTransform ) ;
240
- if ( dict . size > 0 ) {
241
- if ( isTextView ) {
242
- // UITextView's font seems to change inside.
243
- dict . set ( NSFontAttributeName , this . nativeTextViewProtected . font ) ;
244
- }
250
+ // if (style.color && dict.size > 0) {
251
+ // console.log('setTextDecorationAndTransform', style.color);
252
+ // // dict.set(NSForegroundColorAttributeName, style.color.ios);
253
+ // }
245
254
246
- const result = NSMutableAttributedString . alloc ( ) . initWithString ( source ) ;
247
- result . setAttributesRange ( dict as any , { location : 0 , length : source . length } ) ;
248
- if ( this . nativeTextViewProtected instanceof UIButton ) {
249
- this . nativeTextViewProtected . setAttributedTitleForState ( result , UIControlState . Normal ) ;
250
- } else {
251
- this . nativeTextViewProtected . attributedText = result ;
252
- }
253
- } else {
254
- if ( this . nativeTextViewProtected instanceof UIButton ) {
255
- // Clear attributedText or title won't be affected.
256
- this . nativeTextViewProtected . setAttributedTitleForState ( null , UIControlState . Normal ) ;
257
- this . nativeTextViewProtected . setTitleForState ( source , UIControlState . Normal ) ;
258
- } else {
259
- // Clear attributedText or text won't be affected.
260
- this . nativeTextViewProtected . attributedText = undefined ;
261
- this . nativeTextViewProtected . text = source ;
262
- }
263
- }
264
- }
255
+ // const text = this.text;
256
+ // const str = text === undefined || text === null ? '' : text.toString();
257
+ // const source = getTransformedText(str, this.textTransform);
258
+ // if (dict.size > 0) {
259
+ // if (isTextView) {
260
+ // // UITextView's font seems to change inside.
261
+ // dict.set(NSFontAttributeName, this.nativeTextViewProtected.font);
262
+ // }
263
+
264
+ // const result = NSMutableAttributedString.alloc().initWithString(source);
265
+ // result.setAttributesRange(dict as any, { location: 0, length: source.length });
266
+ // if (this.nativeTextViewProtected instanceof UIButton) {
267
+ // this.nativeTextViewProtected.setAttributedTitleForState(result, UIControlState.Normal);
268
+ // } else {
269
+ // this.nativeTextViewProtected.attributedText = result;
270
+ // }
271
+ // } else {
272
+ // if (this.nativeTextViewProtected instanceof UIButton) {
273
+ // // Clear attributedText or title won't be affected.
274
+ // this.nativeTextViewProtected.setAttributedTitleForState(null, UIControlState.Normal);
275
+ // this.nativeTextViewProtected.setTitleForState(source, UIControlState.Normal);
276
+ // } else {
277
+ // // Clear attributedText or text won't be affected.
278
+ // this.nativeTextViewProtected.attributedText = undefined;
279
+ // this.nativeTextViewProtected.text = source;
280
+ // }
281
+ // }
282
+ // }
265
283
266
284
_requestLayoutOnTextChanged ( ) : void {
267
285
if ( this . _fixedSize === FixedSize . BOTH ) {
@@ -300,76 +318,28 @@ export class Label extends LabelBase {
300
318
}
301
319
302
320
htmlText : NSMutableAttributedString ;
303
- // needsHTMLUpdate = false;
304
- // updatingHTML = false;
305
321
updateHTMLString ( ) {
306
- // if (!this.nativeViewProtected || !this.needsHTMLUpdate || this.updatingHTML) {
307
- // return;
308
- // }
309
- // this.updatingHTML = true;
310
322
if ( ! this . html ) {
311
323
this . htmlText = null ;
312
324
} else {
313
325
let htmlString = this . html ;
314
-
315
- let fontFamily ,
316
- fontSize = UIFont . labelFontSize ;
317
- if ( ! ! this . style . fontInternal ) {
318
- if ( ! ! this . style . fontInternal . fontFamily ) {
319
- fontFamily = this . style . fontInternal . fontFamily [ 0 ] === "'" ? this . style . fontInternal . fontFamily . replace ( / ' / g, '' ) : this . style . fontInternal . fontFamily ;
320
- } else {
321
- fontFamily = UIFont . systemFontOfSize ( 10 ) . familyName ;
322
- }
323
- if ( this . style . fontInternal . fontSize ) {
324
- fontSize = this . style . fontInternal . fontSize ;
325
- }
326
- }
327
-
328
- htmlString = `<span style="font-family: ${ fontFamily } ; font-size:${ fontSize } ;">${ htmlString } </span>` ;
326
+ const font = this . nativeView . font ;
327
+ htmlString = `<style>body{ color: ${ this . color } ;font-family: '${ font . familyName } '; font-size:${ font . pointSize } px;}</style>${ htmlString } ` ;
329
328
const nsString = NSString . stringWithString ( htmlString ) ;
330
- const nsData = nsString . dataUsingEncoding ( NSUTF8StringEncoding ) ;
331
- const options = {
332
- [ DTDefaultTextAlignment ] : kCTLeftTextAlignment ,
333
- // [NSTextSizeMultiplierDocumentOption]: 1,
334
- // [DTIgnoreLinkStyleOption]: false,
335
- // [DTDefaultFontFamily]: fontFamily,
336
- // [NSFontAttributeName]: fontFamily,
337
- [ NSTextSizeMultiplierDocumentOption ] : 17 / 12.0 ,
338
- [ DTUseiOS6Attributes ] : true ,
339
- [ DTDocumentPreserveTrailingSpaces ] : true
340
- // [DTDefaultLineBreakMode]: kCTLineBreakByWordWrapping
341
- } as any ;
342
- this . htmlText = NSMutableAttributedString . alloc ( ) . initWithHTMLDataOptionsDocumentAttributes ( nsData , options , null ) ;
343
- this . htmlText . enumerateAttributesInRangeOptionsUsingBlock (
344
- { location : 0 , length : this . htmlText . length } ,
345
- NSAttributedStringEnumerationReverse ,
346
- ( attributes : NSDictionary < any , any > , range , stop ) => {
347
- if ( ! ! attributes . valueForKey ( 'DTGUID' ) ) {
348
- // We need to remove this attribute or links are not colored right
349
- //
350
- // @see https://github.com/Cocoanetics/DTCoreText/issues/792
351
- this . htmlText . removeAttributeRange ( 'CTForegroundColorFromContext' , range ) ;
352
- }
353
- }
329
+ const nsData = nsString . dataUsingEncoding ( NSUTF16StringEncoding ) ;
330
+ this . htmlText = NSMutableAttributedString . alloc ( ) . initWithDataOptionsDocumentAttributesError (
331
+ nsData ,
332
+ < any > {
333
+ [ NSDocumentTypeDocumentAttribute ] : NSHTMLTextDocumentType
334
+ } ,
335
+ null
354
336
) ;
355
- // const nsString = NSString.stringWithString(htmlString);
356
- // const nsData = nsString.dataUsingEncoding(NSUnicodeStringEncoding);
357
- // this.htmlText = NSAttributedString.alloc().initWithDataOptionsDocumentAttributesError(
358
- // nsData,
359
- // <any>{
360
- // [NSDocumentTypeDocumentAttribute]: NSHTMLTextDocumentType
361
- // // [NSCharacterEncodingDocumentAttribute]: NSUTF8StringEncoding
362
- // },
363
- // null
364
- // );
365
-
366
- // this.needsHTMLUpdate = false;
337
+
367
338
this . _requestLayoutOnTextChanged ( ) ;
368
339
}
369
340
if ( this . nativeViewProtected ) {
370
341
this . nativeViewProtected . attributedText = this . htmlText ;
371
342
}
372
- // this.updatingHTML = false;
373
343
}
374
344
applyingNativeSetters = false ;
375
345
public onResumeNativeUpdates ( ) : void {
@@ -378,22 +348,27 @@ export class Label extends LabelBase {
378
348
super . onResumeNativeUpdates ( ) ;
379
349
this . applyingNativeSetters = false ;
380
350
}
351
+ [ colorProperty . setNative ] ( value : Color | UIColor ) {
352
+ const color = value instanceof Color ? value . ios : value ;
353
+ if ( ! this . formattedText && ! this . html ) {
354
+ const nativeView = this . nativeTextViewProtected ;
355
+ nativeView . textColor = color ;
356
+ }
357
+ }
381
358
[ htmlProperty . setNative ] ( value : string ) {
382
- // this.htmlText = value;
383
- // if (this.needsHTMLUpdate || !this.style.fontInternal) {
384
- // this.needsHTMLUpdate = true;
385
359
if ( ! this . style . fontInternal || ! this . applyingNativeSetters ) {
386
360
this . updateHTMLString ( ) ;
387
361
}
388
- // }
362
+ }
363
+ [ formattedTextProperty . setNative ] ( value : FormattedString ) {
364
+ super [ formattedTextProperty . setNative ] ( value )
389
365
}
390
366
[ fontInternalProperty . getDefault ] ( ) : UIFont {
391
367
const nativeView = this . nativeViewProtected ;
392
368
return nativeView . font ;
393
369
}
394
370
[ fontInternalProperty . setNative ] ( value : Font | UIFont ) {
395
371
super [ fontInternalProperty . setNative ] ( value ) ;
396
- // this.needsHTMLUpdate = true;
397
372
// font setter always called after html
398
373
if ( this . html ) {
399
374
this . updateHTMLString ( ) ;
@@ -553,6 +528,7 @@ export class Label extends LabelBase {
553
528
// this.nativeViewProtected.textContainer.maximumNumberOfLines = value as number;
554
529
// }
555
530
// }
531
+
556
532
[ verticalTextAlignmentProperty . setNative ] ( value : VerticalTextAlignment ) {
557
533
this . updateVerticalAlignment ( ) ;
558
534
}
0 commit comments