chore: cleanup

This commit is contained in:
Nathan Walker
2021-02-19 14:51:31 -08:00
parent 621c8302f2
commit 945656fe3e
9 changed files with 117 additions and 60 deletions

View File

@@ -7,9 +7,10 @@ import { TextBaseCommon, textProperty, formattedTextProperty, textAlignmentPrope
import { Color } from '../../color';
import { FormattedString } from './formatted-string';
import { Span } from './span';
import { colorProperty, fontInternalProperty, VerticalAlignment } from '../styling/style-properties';
import { colorProperty, fontInternalProperty, Length, VerticalAlignment } from '../styling/style-properties';
import { isString, isDefined, isNullOrUndefined } from '../../utils/types';
import { iOSNativeHelper } from '../../utils';
import { Trace } from '../../trace';
export * from './text-base-common';
@@ -348,12 +349,10 @@ export class TextBase extends TextBaseCommon {
}
_setShadow(value: TextShadow): void {
let layer;
if (this.nativeTextViewProtected instanceof UITextView) {
layer = this.nativeTextViewProtected.layer.sublayers.objectAtIndex(1);
} else {
layer = this.nativeTextViewProtected.layer;
const layer = getShadowLayer(this);
if (!layer) {
Trace.write('text-shadow not applied, no layer.', Trace.categories.Style, Trace.messageType.info);
return;
}
if (isNullOrUndefined(value)) {
@@ -365,12 +364,24 @@ export class TextBase extends TextBaseCommon {
return;
}
layer.shadowOpacity = 1;
layer.shadowRadius = value.blurRadius;
layer.shadowColor = value.color.ios.CGColor;
layer.shadowOffset = CGSizeMake(value.offsetX, value.offsetY);
layer.shouldRasterize = true;
if (value.color) {
layer.shadowOpacity = value.color.a / 255;
layer.shadowColor = value.color.ios.CGColor;
}
if (value.blurRadius) {
layer.shadowRadius = Length.toDevicePixels(value.blurRadius);
}
layer.shadowOffset = CGSizeMake(Length.toDevicePixels(value.offsetX), Length.toDevicePixels(value.offsetY));
// layer.shadowOffset = CGSizeMake(Length.toDevicePixels(value.offsetX), Length.toDevicePixels(value.offsetY));
layer.masksToBounds = false;
// NOTE: generally should not need shouldRaterize
// however for various detailed animation work which involves text-shadow applicable layers, we may want to give users the control of enabling this with text-shadow
// if (!(this.nativeTextViewProtected instanceof UITextView)) {
// layer.shouldRasterize = true;
// }
}
createNSMutableAttributedString(formattedString: FormattedString): NSMutableAttributedString {
@@ -493,6 +504,41 @@ export function getTransformedText(text: string, textTransform: TextTransform):
}
}
export function getShadowLayer(view: TextBase): CALayer {
let layer: CALayer;
const name = 'shadow-layer';
const nativeView = view && view.nativeTextViewProtected;
if (nativeView) {
if (nativeView.layer) {
if (nativeView.layer.name === name) {
return nativeView.layer;
} else {
if (nativeView.layer.sublayers && nativeView.layer.sublayers.count) {
console.log('this.nativeTextViewProtected.layer.sublayers.count:', nativeView.layer.sublayers.count);
for (let i = 0; i < nativeView.layer.sublayers.count; i++) {
console.log(`layer ${i}:`, nativeView.layer.sublayers.objectAtIndex(i));
if (nativeView.layer.sublayers.objectAtIndex(i).name === name) {
return nativeView.layer.sublayers.objectAtIndex(i);
}
}
if (nativeView instanceof UITextView) {
layer = nativeView.layer.sublayers.objectAtIndex(1);
} else {
layer = nativeView.layer.sublayers.objectAtIndex(nativeView.layer.sublayers.count - 1);
}
} else {
layer = nativeView.layer;
}
}
} else {
// could this occur?
console.log('no layer!');
}
}
layer.name = name;
return layer;
}
function NSStringFromNSAttributedString(source: NSAttributedString | string): NSString {
return NSString.stringWithString((source instanceof NSAttributedString && source.string) || <string>source);
}

View File

@@ -9,12 +9,13 @@ import { Span } from './span';
import { View } from '../core/view';
import { Property, CssProperty, InheritedCssProperty, makeValidator, makeParser } from '../core/properties';
import { Style } from '../styling/style';
import { Length } from '../styling/style-properties';
import { Length, parseShadowProperites } from '../styling/style-properties';
import { Observable } from '../../data/observable';
import { TextAlignment, TextDecoration, TextTransform, WhiteSpace, TextShadow } from './text-base-interfaces';
import { TextAlignment, TextDecoration, TextTransform, WhiteSpace } from './text-base-interfaces';
import { TextBase as TextBaseDefinition } from '.';
import { Color } from '../../color';
import { CSSShadow } from '../styling/css-shadow';
export * from './text-base-interfaces';
@@ -27,6 +28,26 @@ export abstract class TextBaseCommon extends View implements TextBaseDefinition
public text: string;
public formattedText: FormattedString;
/***
* In the NativeScript Core; by default the nativeTextViewProtected points to the same value as nativeViewProtected.
* At this point no internal NS components need this indirection functionality.
* This indirection is used to allow support usage by third party components so they don't have to duplicate functionality.
*
* A third party component can just override the `nativeTextViewProtected` getter and return a different internal view and that view would be
* what all TextView/TextInput class features would be applied to.
*
* A example is the Android MaterialDesign TextInput class, it has a wrapper view of a TextInputLayout
* https://developer.android.com/reference/com/google/android/material/textfield/TextInputLayout
* which wraps the actual TextInput. This wrapper layout (TextInputLayout) must be assigned to the nativeViewProtected as the entire
* NS Core uses nativeViewProtected for everything related to layout, so that it can be measured, added to the parent view as a child, ect.
*
* However, its internal view would be the actual TextView/TextInput and to allow that sub-view to have the normal TextView/TextInput
* class features, which we expose and to allow them to work on it, the internal TextView/TextInput is what the needs to have the class values applied to it.
*
* So all code that works on what is expected to be a TextView/TextInput should use `nativeTextViewProtected` so that any third party
* components that need to have two separate components can work properly without them having to duplicate all the TextBase (and decendants) functionality
* by just overriding the nativeTextViewProtected getter.
**/
get nativeTextViewProtected() {
return this.nativeViewProtected;
}
@@ -247,18 +268,12 @@ export const textTransformProperty = new CssProperty<Style, TextTransform>({
});
textTransformProperty.register(Style);
export const textShadowProperty = new CssProperty<Style, string | TextShadow>({
export const textShadowProperty = new CssProperty<Style, string | CSSShadow>({
name: 'textShadow',
cssName: 'text-shadow',
affectsLayout: global.isIOS,
valueConverter: (value) => {
const params = value.split(' ');
return {
offsetX: Length.parse(params[0]),
offsetY: Length.parse(params[1]),
blurRadius: Length.parse(params[2]),
color: new Color(params.slice(3).join('')),
};
return parseShadowProperites(value);
},
});
textShadowProperty.register(Style);

View File

@@ -5,9 +5,3 @@ export type WhiteSpace = 'initial' | 'normal' | 'nowrap';
export type TextAlignment = 'initial' | 'left' | 'center' | 'right';
export type TextTransform = 'initial' | 'none' | 'capitalize' | 'uppercase' | 'lowercase';
export type TextDecoration = 'none' | 'underline' | 'line-through' | 'underline line-through';
export type TextShadow = {
offsetX: Length;
offsetY: Length;
blurRadius: Length;
color: Color;
};