chore: cleanup

This commit is contained in:
Nathan Walker
2021-02-19 14:51:31 -08:00
parent a12c188d0f
commit 673387cf99
9 changed files with 117 additions and 60 deletions

View File

@ -1,6 +1,6 @@
import { EventData, TextBase } from '@nativescript/core'; import { EventData, TextBase } from '@nativescript/core';
const possibleValues = ['2 10 4 rgb(255, 100, 100)', '2 10 2 rgba(10, 10, 10, 0.5)', '1 1 1 #55a', '2 2 2 #aaa', '']; const possibleValues = ['2 10 4 rgb(255, 100, 100)', '2 10 2 rgba(10, 10, 10, 0.5)', '1 1 1 #55a', '2 2 2 #aaa', '0 0 1 yellow', '-1 -1 1 #aaa', ''];
let currentIndex = 0; let currentIndex = 0;
export function butonTap(args: EventData) { export function butonTap(args: EventData) {

View File

@ -25,7 +25,7 @@ import * as am from '../../animation';
import { AccessibilityLiveRegion, AccessibilityRole, AccessibilityState, AccessibilityTrait, AndroidAccessibilityEvent, IOSPostAccessibilityNotificationType } from '../../../accessibility/accessibility-types'; import { AccessibilityLiveRegion, AccessibilityRole, AccessibilityState, AccessibilityTrait, AndroidAccessibilityEvent, IOSPostAccessibilityNotificationType } from '../../../accessibility/accessibility-types';
import { accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityTraitsProperty, accessibilityValueProperty } from '../../../accessibility/accessibility-properties'; import { accessibilityHintProperty, accessibilityIdentifierProperty, accessibilityLabelProperty, accessibilityTraitsProperty, accessibilityValueProperty } from '../../../accessibility/accessibility-properties';
import { accessibilityBlurEvent, accessibilityFocusChangedEvent, accessibilityFocusEvent, getCurrentFontScale } from '../../../accessibility'; import { accessibilityBlurEvent, accessibilityFocusChangedEvent, accessibilityFocusEvent, getCurrentFontScale } from '../../../accessibility';
import { BoxShadow } from '../../styling/box-shadow'; import { CSSShadow } from '../../styling/css-shadow';
// helpers (these are okay re-exported here) // helpers (these are okay re-exported here)
export * from './view-helper'; export * from './view-helper';
@ -591,10 +591,10 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
this.style.backgroundRepeat = value; this.style.backgroundRepeat = value;
} }
get boxShadow(): BoxShadow { get boxShadow(): CSSShadow {
return this.style.boxShadow; return this.style.boxShadow;
} }
set boxShadow(value: BoxShadow) { set boxShadow(value: CSSShadow) {
this.style.boxShadow = value; this.style.boxShadow = value;
} }

View File

@ -7,7 +7,7 @@ import { Color } from '../../color';
import { isDataURI, isFileOrResourcePath, layout } from '../../utils'; import { isDataURI, isFileOrResourcePath, layout } from '../../utils';
import { ImageSource } from '../../image-source'; import { ImageSource } from '../../image-source';
import { CSSValue, parse as cssParse } from '../../css-value'; import { CSSValue, parse as cssParse } from '../../css-value';
import { BoxShadow } from './box-shadow'; import { CSSShadow } from './css-shadow';
export * from './background-common'; export * from './background-common';
@ -717,7 +717,7 @@ function drawNoRadiusNonUniformBorders(nativeView: NativeView, background: Backg
} }
// TODO: use sublayer if its applied to a layout // TODO: use sublayer if its applied to a layout
function drawBoxShadow(nativeView: NativeView, view: View, boxShadow: BoxShadow, background: BackgroundDefinition, useSubLayer: boolean = false) { function drawBoxShadow(nativeView: NativeView, view: View, boxShadow: CSSShadow, background: BackgroundDefinition, useSubLayer: boolean = false) {
const layer: CALayer = nativeView.layer; const layer: CALayer = nativeView.layer;
layer.masksToBounds = false; layer.masksToBounds = false;

View File

@ -1,6 +1,6 @@
import { Color } from '../../color'; import { Color } from '../../color';
export class BoxShadow { export class CSSShadow {
public offsetX: number; public offsetX: number;
public offsetY: number; public offsetY: number;
public blurRadius: number; public blurRadius: number;

View File

@ -17,7 +17,7 @@ import { Trace } from '../../trace';
import * as parser from '../../css/parser'; import * as parser from '../../css/parser';
import { LinearGradient } from './linear-gradient'; import { LinearGradient } from './linear-gradient';
import { BoxShadow } from './box-shadow'; import { CSSShadow } from './css-shadow';
export type LengthDipUnit = { readonly unit: 'dip'; readonly value: dip }; export type LengthDipUnit = { readonly unit: 'dip'; readonly value: dip };
export type LengthPxUnit = { readonly unit: 'px'; readonly value: px }; export type LengthPxUnit = { readonly unit: 'px'; readonly value: px };
@ -452,10 +452,10 @@ export const verticalAlignmentProperty = new CssProperty<Style, VerticalAlignmen
}); });
verticalAlignmentProperty.register(Style); verticalAlignmentProperty.register(Style);
function parseBoxShadowProperites(value: string): BoxShadow { export function parseShadowProperites(value: string): CSSShadow {
if (typeof value === 'string') { if (typeof value === 'string') {
let arr; let arr;
let colorRaw; let colorRaw = 'black';
if (value.indexOf('rgb') > -1) { if (value.indexOf('rgb') > -1) {
arr = value.split(' '); arr = value.split(' ');
colorRaw = arr.pop(); colorRaw = arr.pop();
@ -464,27 +464,29 @@ function parseBoxShadowProperites(value: string): BoxShadow {
colorRaw = arr.pop(); colorRaw = arr.pop();
} }
let offsetX: number; let offsetX = 0;
let offsetY: number; let offsetY = 0;
let blurRadius: number; // not currently in use let blurRadius = 0; // not currently in use
let spreadRadius: number; // maybe rename this to just radius let spreadRadius = 0; // maybe rename this to just radius
let color: Color = new Color(colorRaw); let color: Color = new Color(colorRaw);
if (arr.length === 2) { if (arr.length === 1) {
offsetX = parseFloat(arr[0]); Trace.write('Expected 3, 4 or 5 parameters. Actual: ' + value, Trace.categories.Error, Trace.messageType.error);
offsetY = parseFloat(arr[1]);
} else if (arr.length === 3) {
offsetX = parseFloat(arr[0]);
offsetY = parseFloat(arr[1]);
blurRadius = parseFloat(arr[2]);
} else if (arr.length === 4) {
offsetX = parseFloat(arr[0]);
offsetY = parseFloat(arr[1]);
blurRadius = parseFloat(arr[2]);
spreadRadius = parseFloat(arr[3]);
} else {
throw new Error('Expected 3, 4 or 5 parameters. Actual: ' + value);
} }
if (arr.length > 1) {
offsetX = parseFloat(arr[0]);
offsetY = parseFloat(arr[1]);
}
if (arr.length > 2) {
blurRadius = parseFloat(arr[2]);
}
if (arr.length > 3) {
spreadRadius = parseFloat(arr[3]);
}
return { return {
offsetX: offsetX, offsetX: offsetX,
offsetY: offsetY, offsetY: offsetY,
@ -1321,14 +1323,14 @@ export const borderBottomLeftRadiusProperty = new CssProperty<Style, Length>({
}); });
borderBottomLeftRadiusProperty.register(Style); borderBottomLeftRadiusProperty.register(Style);
const boxShadowProperty = new CssProperty<Style, BoxShadow>({ const boxShadowProperty = new CssProperty<Style, CSSShadow>({
name: 'boxShadow', name: 'boxShadow',
cssName: 'box-shadow', cssName: 'box-shadow',
valueChanged: (target, oldValue, newValue) => { valueChanged: (target, oldValue, newValue) => {
target.boxShadow = newValue; target.boxShadow = newValue;
}, },
valueConverter: (value) => { valueConverter: (value) => {
return parseBoxShadowProperites(value); return parseShadowProperites(value);
}, },
}); });
boxShadowProperty.register(Style); boxShadowProperty.register(Style);

View File

@ -12,7 +12,7 @@ import { FlexDirection, FlexWrap, JustifyContent, AlignItems, AlignContent, Orde
import { Trace } from '../../../trace'; import { Trace } from '../../../trace';
import { TextAlignment, TextDecoration, TextTransform, WhiteSpace, TextShadow } from '../../text-base'; import { TextAlignment, TextDecoration, TextTransform, WhiteSpace, TextShadow } from '../../text-base';
import { AccessibilityLiveRegion, AccessibilityRole, AccessibilityState } from '../../../accessibility/accessibility-types'; import { AccessibilityLiveRegion, AccessibilityRole, AccessibilityState } from '../../../accessibility/accessibility-types';
import { BoxShadow } from '../box-shadow'; import { CSSShadow } from '../css-shadow';
export interface CommonLayoutParams { export interface CommonLayoutParams {
width: number; width: number;
@ -140,7 +140,7 @@ export class Style extends Observable implements StyleDefinition {
public borderBottomRightRadius: Length; public borderBottomRightRadius: Length;
public borderBottomLeftRadius: Length; public borderBottomLeftRadius: Length;
public boxShadow: BoxShadow; public boxShadow: CSSShadow;
public fontSize: number; public fontSize: number;
public fontFamily: string; public fontFamily: string;

View File

@ -7,9 +7,10 @@ import { TextBaseCommon, textProperty, formattedTextProperty, textAlignmentPrope
import { Color } from '../../color'; import { Color } from '../../color';
import { FormattedString } from './formatted-string'; import { FormattedString } from './formatted-string';
import { Span } from './span'; 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 { isString, isDefined, isNullOrUndefined } from '../../utils/types';
import { iOSNativeHelper } from '../../utils'; import { iOSNativeHelper } from '../../utils';
import { Trace } from '../../trace';
export * from './text-base-common'; export * from './text-base-common';
@ -348,12 +349,10 @@ export class TextBase extends TextBaseCommon {
} }
_setShadow(value: TextShadow): void { _setShadow(value: TextShadow): void {
let layer; const layer = getShadowLayer(this);
if (!layer) {
if (this.nativeTextViewProtected instanceof UITextView) { Trace.write('text-shadow not applied, no layer.', Trace.categories.Style, Trace.messageType.info);
layer = this.nativeTextViewProtected.layer.sublayers.objectAtIndex(1); return;
} else {
layer = this.nativeTextViewProtected.layer;
} }
if (isNullOrUndefined(value)) { if (isNullOrUndefined(value)) {
@ -365,12 +364,24 @@ export class TextBase extends TextBaseCommon {
return; return;
} }
layer.shadowOpacity = 1; if (value.color) {
layer.shadowRadius = value.blurRadius; layer.shadowOpacity = value.color.a / 255;
layer.shadowColor = value.color.ios.CGColor; layer.shadowColor = value.color.ios.CGColor;
layer.shadowOffset = CGSizeMake(value.offsetX, value.offsetY); }
layer.shouldRasterize = true;
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; 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 { 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 { function NSStringFromNSAttributedString(source: NSAttributedString | string): NSString {
return NSString.stringWithString((source instanceof NSAttributedString && source.string) || <string>source); 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 { View } from '../core/view';
import { Property, CssProperty, InheritedCssProperty, makeValidator, makeParser } from '../core/properties'; import { Property, CssProperty, InheritedCssProperty, makeValidator, makeParser } from '../core/properties';
import { Style } from '../styling/style'; import { Style } from '../styling/style';
import { Length } from '../styling/style-properties'; import { Length, parseShadowProperites } from '../styling/style-properties';
import { Observable } from '../../data/observable'; 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 { TextBase as TextBaseDefinition } from '.';
import { Color } from '../../color'; import { Color } from '../../color';
import { CSSShadow } from '../styling/css-shadow';
export * from './text-base-interfaces'; export * from './text-base-interfaces';
@ -27,6 +28,26 @@ export abstract class TextBaseCommon extends View implements TextBaseDefinition
public text: string; public text: string;
public formattedText: FormattedString; 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() { get nativeTextViewProtected() {
return this.nativeViewProtected; return this.nativeViewProtected;
} }
@ -247,18 +268,12 @@ export const textTransformProperty = new CssProperty<Style, TextTransform>({
}); });
textTransformProperty.register(Style); textTransformProperty.register(Style);
export const textShadowProperty = new CssProperty<Style, string | TextShadow>({ export const textShadowProperty = new CssProperty<Style, string | CSSShadow>({
name: 'textShadow', name: 'textShadow',
cssName: 'text-shadow', cssName: 'text-shadow',
affectsLayout: global.isIOS, affectsLayout: global.isIOS,
valueConverter: (value) => { valueConverter: (value) => {
const params = value.split(' '); return parseShadowProperites(value);
return {
offsetX: Length.parse(params[0]),
offsetY: Length.parse(params[1]),
blurRadius: Length.parse(params[2]),
color: new Color(params.slice(3).join('')),
};
}, },
}); });
textShadowProperty.register(Style); textShadowProperty.register(Style);

View File

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