mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
Improve background setter in iOS (#3582)
CoercableProperty now inherits from Property VS Code typescript sdk removed ViewBase will no longer clear native view if recycleNativeView is false
This commit is contained in:
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@@ -1,4 +0,0 @@
|
||||
// Place your settings in this file to overwrite default and user settings.
|
||||
{
|
||||
"typescript.tsdk": "node_modules/typescript/lib"
|
||||
}
|
||||
52
tests/.vscode/launch.json
vendored
52
tests/.vscode/launch.json
vendored
@@ -1,77 +1,41 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Sync on iOS",
|
||||
"type": "nativescript",
|
||||
"platform": "ios",
|
||||
"request": "launch",
|
||||
"appRoot": "${workspaceRoot}",
|
||||
"sourceMaps": true,
|
||||
"diagnosticLogging": false,
|
||||
"emulator": false,
|
||||
"rebuild": false,
|
||||
"syncAllFiles": true,
|
||||
"stopOnEntry": true
|
||||
},
|
||||
{
|
||||
"name": "Launch on iOS",
|
||||
"type": "nativescript",
|
||||
"platform": "ios",
|
||||
"request": "launch",
|
||||
"platform": "ios",
|
||||
"appRoot": "${workspaceRoot}",
|
||||
"sourceMaps": true,
|
||||
"diagnosticLogging": false,
|
||||
"emulator": false,
|
||||
"rebuild": true,
|
||||
"stopOnEntry": true
|
||||
"watch": true
|
||||
},
|
||||
{
|
||||
"name": "Attach on iOS",
|
||||
"type": "nativescript",
|
||||
"platform": "ios",
|
||||
"request": "attach",
|
||||
"platform": "ios",
|
||||
"appRoot": "${workspaceRoot}",
|
||||
"sourceMaps": true,
|
||||
"diagnosticLogging": false,
|
||||
"emulator": false,
|
||||
"stopOnEntry": true
|
||||
},
|
||||
{
|
||||
"name": "Sync on Android",
|
||||
"type": "nativescript",
|
||||
"platform": "android",
|
||||
"request": "launch",
|
||||
"appRoot": "${workspaceRoot}",
|
||||
"sourceMaps": true,
|
||||
"diagnosticLogging": false,
|
||||
"emulator": false,
|
||||
"rebuild": false,
|
||||
"syncAllFiles": true,
|
||||
"stopOnEntry": true
|
||||
"watch": false
|
||||
},
|
||||
{
|
||||
"name": "Launch on Android",
|
||||
"type": "nativescript",
|
||||
"platform": "android",
|
||||
"request": "launch",
|
||||
"platform": "android",
|
||||
"appRoot": "${workspaceRoot}",
|
||||
"sourceMaps": true,
|
||||
"diagnosticLogging": false,
|
||||
"emulator": false,
|
||||
"rebuild": true,
|
||||
"stopOnEntry": true
|
||||
"watch": true
|
||||
},
|
||||
{
|
||||
"name": "Attach on Android",
|
||||
"type": "nativescript",
|
||||
"platform": "android",
|
||||
"request": "attach",
|
||||
"platform": "android",
|
||||
"appRoot": "${workspaceRoot}",
|
||||
"sourceMaps": true,
|
||||
"diagnosticLogging": false,
|
||||
"emulator": false,
|
||||
"stopOnEntry": true
|
||||
"watch": false
|
||||
}
|
||||
]
|
||||
}
|
||||
3
tests/.vscode/settings.json
vendored
3
tests/.vscode/settings.json
vendored
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"typescript.tsdk": "./node_modules/typescript/lib"
|
||||
}
|
||||
@@ -6,14 +6,14 @@
|
||||
"nativescript": {
|
||||
"id": "org.nativescript.tests",
|
||||
"tns-ios": {
|
||||
"version": "2.4.0"
|
||||
"version": "2.5.0"
|
||||
},
|
||||
"tns-android": {
|
||||
"version": "2.4.1"
|
||||
"version": "2.5.0"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"tns-core-modules": "2.4.0"
|
||||
"tns-core-modules": "2.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tns-platform-declarations": "*",
|
||||
|
||||
@@ -38,7 +38,7 @@ const enum ValueSource {
|
||||
Local = 3
|
||||
}
|
||||
|
||||
export class Property<T extends ViewBase, U> implements PropertyDescriptor, definitions.Property<T, U> {
|
||||
export class Property<T extends ViewBase, U> implements TypedPropertyDescriptor<U>, definitions.Property<T, U> {
|
||||
private registered: boolean;
|
||||
|
||||
public readonly name: string;
|
||||
@@ -174,40 +174,20 @@ export class Property<T extends ViewBase, U> implements PropertyDescriptor, defi
|
||||
}
|
||||
}
|
||||
|
||||
export class CoercibleProperty<T extends ViewBase, U> implements PropertyDescriptor, definitions.CoercibleProperty<T, U> {
|
||||
private registered: boolean;
|
||||
private readonly name: string;
|
||||
public readonly key: symbol;
|
||||
public readonly native: symbol;
|
||||
public readonly defaultValueKey: symbol;
|
||||
public readonly defaultValue: U;
|
||||
public readonly nativeValueChange: (owner: T, value: U) => void;
|
||||
|
||||
public readonly get: () => U;
|
||||
public readonly set: (value: U) => void;
|
||||
public readonly enumerable: boolean = true;
|
||||
public readonly configurable: boolean = true;
|
||||
|
||||
export class CoercibleProperty<T extends ViewBase, U> extends Property<T, U> implements definitions.CoercibleProperty<T, U> {
|
||||
public readonly coerce: (target: T) => void;
|
||||
|
||||
constructor(options: definitions.CoerciblePropertyOptions<T, U>) {
|
||||
super(options);
|
||||
|
||||
const name = options.name;
|
||||
this.name = name;
|
||||
|
||||
const key = Symbol(name + ":propertyKey");
|
||||
this.key = key;
|
||||
|
||||
const native: symbol = Symbol(name + ":nativeKey");
|
||||
this.native = native;
|
||||
|
||||
const defaultValueKey = Symbol(name + ":nativeDefaultValue");
|
||||
this.defaultValueKey = defaultValueKey;
|
||||
const key = this.key;
|
||||
const native: symbol = this.native;
|
||||
const defaultValueKey = this.defaultValueKey;
|
||||
const defaultValue: U = this.defaultValue;
|
||||
|
||||
const coerceKey = Symbol(name + ":coerceKey");
|
||||
|
||||
const defaultValue: U = options.defaultValue;
|
||||
this.defaultValue = defaultValue;
|
||||
|
||||
const eventName = name + "Change";
|
||||
const affectsLayout: boolean = options.affectsLayout;
|
||||
const equalityComparer = options.equalityComparer;
|
||||
@@ -218,8 +198,8 @@ export class CoercibleProperty<T extends ViewBase, U> implements PropertyDescrip
|
||||
this.coerce = function (target: T): void {
|
||||
const originalValue: U = coerceKey in target ? target[coerceKey] : defaultValue;
|
||||
// need that to make coercing but also fire change events
|
||||
this.set.call(target, originalValue);
|
||||
};
|
||||
target[name] = originalValue;
|
||||
}
|
||||
|
||||
this.set = function (this: T, value: U): void {
|
||||
const reset = value === unsetValue;
|
||||
@@ -283,46 +263,7 @@ export class CoercibleProperty<T extends ViewBase, U> implements PropertyDescrip
|
||||
this.requestLayout();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.get = function (): U {
|
||||
return key in this ? this[key] : defaultValue;
|
||||
};
|
||||
|
||||
this.nativeValueChange = function (owner: T, value: U): void {
|
||||
const currentValue = key in owner ? owner[key] : defaultValue;
|
||||
const changed = equalityComparer ? !equalityComparer(currentValue, value) : currentValue !== value;
|
||||
if (changed) {
|
||||
owner[key] = value;
|
||||
owner[coerceKey] = value;
|
||||
if (valueChanged) {
|
||||
valueChanged(owner, currentValue, value);
|
||||
}
|
||||
|
||||
if (owner.hasListeners(eventName)) {
|
||||
owner.notify({
|
||||
eventName: eventName,
|
||||
propertyName: name,
|
||||
object: owner,
|
||||
value: value
|
||||
});
|
||||
}
|
||||
|
||||
if (affectsLayout) {
|
||||
owner.requestLayout();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
symbolPropertyMap[key] = this;
|
||||
}
|
||||
|
||||
public register(cls: { prototype: T }): void {
|
||||
if (this.registered) {
|
||||
throw new Error(`Property ${this.name} already registered.`);
|
||||
}
|
||||
this.registered = true;
|
||||
Object.defineProperty(cls.prototype, this.name, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -832,7 +773,7 @@ function inheritableCssPropertyValuesOn(style: Style): Array<{ property: Inherit
|
||||
return array;
|
||||
}
|
||||
|
||||
export function applyNativeSetters(view: ViewBase): void {
|
||||
export function initNativeView(view: ViewBase): void {
|
||||
let symbols = (<any>Object).getOwnPropertySymbols(view);
|
||||
for (let symbol of symbols) {
|
||||
const property: Property<any, any> = symbolPropertyMap[symbol];
|
||||
@@ -873,6 +814,44 @@ export function applyNativeSetters(view: ViewBase): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function resetNativeView(view: ViewBase): void {
|
||||
let symbols = (<any>Object).getOwnPropertySymbols(view);
|
||||
for (let symbol of symbols) {
|
||||
const property: Property<any, any> = symbolPropertyMap[symbol];
|
||||
if (!property) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const native = property.native;
|
||||
if (native in view) {
|
||||
view[native] = view[property.defaultValueKey];
|
||||
delete view[property.defaultValueKey];
|
||||
}
|
||||
|
||||
// This will not call propertyChange!!!
|
||||
delete view[property.key];
|
||||
}
|
||||
|
||||
const style = view.style;
|
||||
|
||||
symbols = (<any>Object).getOwnPropertySymbols(style);
|
||||
for (let symbol of symbols) {
|
||||
const property: CssProperty<any, any> = cssSymbolPropertyMap[symbol];
|
||||
if (!property) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const native = property.native;
|
||||
if (native in view) {
|
||||
view[native] = style[property.defaultValueKey];
|
||||
delete style[property.defaultValueKey];
|
||||
}
|
||||
|
||||
// This will not call propertyChange!!!
|
||||
delete style[property.key];
|
||||
}
|
||||
}
|
||||
|
||||
export function clearInheritedProperties(view: ViewBase): void {
|
||||
for (let prop of inheritableProperties) {
|
||||
const sourceKey = prop.sourceKey;
|
||||
@@ -902,26 +881,6 @@ export function resetCSSProperties(style: Style): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function resetStyleProperties(style: Style): void {
|
||||
let symbols = (<any>Object).getOwnPropertySymbols(style);
|
||||
const view = style.view;
|
||||
for (let symbol of symbols) {
|
||||
const property: CssProperty<any, any> = symbolPropertyMap[symbol];
|
||||
if (!property) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const native = property.native;
|
||||
if (native in view) {
|
||||
view[native] = style[property.defaultValueKey];
|
||||
delete style[property.defaultValueKey];
|
||||
}
|
||||
|
||||
// This will not call propertyChange!!!
|
||||
delete style[property.key];
|
||||
}
|
||||
}
|
||||
|
||||
export function propagateInheritedProperties(view: ViewBase): void {
|
||||
const inheritablePropertyValues = inheritablePropertyValuesOn(view);
|
||||
const inheritableCssPropertyValues = inheritableCssPropertyValuesOn(view.style);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ViewBase as ViewBaseDefinition } from "ui/core/view-base";
|
||||
import { Observable, EventData, PropertyChangeData } from "data/observable";
|
||||
import { Property, InheritedProperty, Style, clearInheritedProperties, propagateInheritedProperties, resetCSSProperties, applyNativeSetters, resetStyleProperties } from "./properties";
|
||||
import { Property, InheritedProperty, Style, clearInheritedProperties, propagateInheritedProperties, resetCSSProperties, initNativeView, resetNativeView } from "./properties";
|
||||
import { Binding, BindingOptions } from "ui/core/bindable";
|
||||
import { isIOS, isAndroid } from "platform";
|
||||
import { fromString as gestureFromString } from "ui/gestures";
|
||||
@@ -107,6 +107,8 @@ export function eachDescendant(view: ViewBaseDefinition, callback: (child: ViewB
|
||||
let viewIdCounter = 0;
|
||||
|
||||
export class ViewBase extends Observable implements ViewBaseDefinition {
|
||||
public recycleNativeView: boolean;
|
||||
|
||||
private _style: Style;
|
||||
private _isLoaded: boolean;
|
||||
private _registeredAnimations: Array<KeyframeAnimation>;
|
||||
@@ -505,7 +507,9 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
|
||||
}
|
||||
|
||||
public _resetNativeView(): void {
|
||||
//
|
||||
if (this.nativeView && this.recycleNativeView) {
|
||||
resetNativeView(this);
|
||||
}
|
||||
}
|
||||
|
||||
public _setupUI(context: android.content.Context, atIndex?: number) {
|
||||
@@ -533,7 +537,7 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
|
||||
}
|
||||
|
||||
if (this.nativeView) {
|
||||
applyNativeSetters(this);
|
||||
initNativeView(this);
|
||||
}
|
||||
|
||||
this.eachChild((child) => {
|
||||
@@ -552,11 +556,6 @@ export class ViewBase extends Observable implements ViewBaseDefinition {
|
||||
return true;
|
||||
});
|
||||
|
||||
if (this.nativeView) {
|
||||
// TODO: rename and implement this as resetNativeSetters
|
||||
resetStyleProperties(this.style);
|
||||
}
|
||||
|
||||
if (this.parent) {
|
||||
this.parent._removeViewFromNativeVisualTree(this);
|
||||
}
|
||||
|
||||
11
tns-core-modules/ui/definitions.d.ts
vendored
11
tns-core-modules/ui/definitions.d.ts
vendored
@@ -54,6 +54,7 @@ declare module "ui/core/view-base" {
|
||||
public android: any;
|
||||
public nativeView: any;
|
||||
public bindingContext: any;
|
||||
public recycleNativeView: boolean;
|
||||
|
||||
/**
|
||||
* Gets the name of the constructor function for this instance. E.g. for a Button class this will return "Button".
|
||||
@@ -225,14 +226,10 @@ declare module "ui/core/properties" {
|
||||
public nativeValueChange(T, U): void;
|
||||
}
|
||||
|
||||
export class CoercibleProperty<T extends ViewBase, U> implements TypedPropertyDescriptor<U> {
|
||||
export class CoercibleProperty<T extends ViewBase, U> extends Property<T, U> implements TypedPropertyDescriptor<U> {
|
||||
constructor(options: CoerciblePropertyOptions<T, U>);
|
||||
|
||||
public readonly native: symbol;
|
||||
public readonly defaultValue: U;
|
||||
public readonly coerce: (target: T) => void;
|
||||
public register(cls: { prototype: T }): void;
|
||||
public nativeValueChange(T, U): void;
|
||||
}
|
||||
|
||||
export class InheritedProperty<T extends ViewBase, U> extends Property<T, U> {
|
||||
@@ -269,8 +266,8 @@ declare module "ui/core/properties" {
|
||||
public register(cls: { prototype: T }): void;
|
||||
}
|
||||
|
||||
export function applyNativeSetters(view: ViewBase): void;
|
||||
export function resetStyleProperties(style: Style): void;
|
||||
export function initNativeView(view: ViewBase): void;
|
||||
export function resetNativeView(view: ViewBase): void;
|
||||
export function resetCSSProperties(style: Style): void;
|
||||
|
||||
export function makeValidator<T>(...values: T[]): (value: any) => value is T;
|
||||
|
||||
@@ -64,7 +64,7 @@ export class Label extends TextBase implements LabelDefinition {
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
let nativeView = this._nativeView;
|
||||
let nativeView = this.nativeView;
|
||||
if (nativeView) {
|
||||
let width = layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
let widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
@@ -119,33 +119,23 @@ export class Label extends TextBase implements LabelDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
get [backgroundInternalProperty.native](): UIColor {
|
||||
let nativeView = this._nativeView;
|
||||
if (nativeView.layer && nativeView.layer.backgroundColor) {
|
||||
return UIColor.colorWithCGColor(nativeView.layer.backgroundColor);
|
||||
get [backgroundInternalProperty.native](): any /* CGColor */ {
|
||||
return this.nativeView.layer.backgroundColor;
|
||||
}
|
||||
set [backgroundInternalProperty.native](value: Background) {
|
||||
if (value instanceof Background) {
|
||||
const uiColor = <UIColor>ios.createBackgroundUIColor(this, true);
|
||||
value = uiColor ? uiColor.CGColor : null;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
set [backgroundInternalProperty.native](value: UIColor | Background) {
|
||||
let nativeView = this._nativeView;
|
||||
|
||||
let cgColor = null;
|
||||
if (value instanceof UIColor) {
|
||||
cgColor = value.CGColor;
|
||||
} else {
|
||||
let uiColor = <UIColor>ios.createBackgroundUIColor(this, true);
|
||||
cgColor = uiColor ? uiColor.CGColor : null;
|
||||
}
|
||||
|
||||
nativeView.layer.backgroundColor = cgColor;
|
||||
this.nativeView.layer.backgroundColor = value;
|
||||
}
|
||||
|
||||
get [borderTopWidthProperty.native](): Length {
|
||||
return zeroLength;
|
||||
}
|
||||
set [borderTopWidthProperty.native](value: Length) {
|
||||
let nativeView = this._nativeView;
|
||||
let nativeView = this.nativeView;
|
||||
let border = nativeView.borderThickness;
|
||||
nativeView.borderThickness = {
|
||||
top: this.effectiveBorderTopWidth,
|
||||
@@ -159,7 +149,7 @@ export class Label extends TextBase implements LabelDefinition {
|
||||
return zeroLength;
|
||||
}
|
||||
set [borderRightWidthProperty.native](value: Length) {
|
||||
let nativeView = this._nativeView;
|
||||
let nativeView = this.nativeView;
|
||||
let border = nativeView.borderThickness;
|
||||
nativeView.borderThickness = {
|
||||
top: border.top,
|
||||
@@ -173,7 +163,7 @@ export class Label extends TextBase implements LabelDefinition {
|
||||
return zeroLength;
|
||||
}
|
||||
set [borderBottomWidthProperty.native](value: Length) {
|
||||
let nativeView = this._nativeView;
|
||||
let nativeView = this.nativeView;
|
||||
let border = nativeView.borderThickness;
|
||||
nativeView.borderThickness = {
|
||||
top: border.top,
|
||||
@@ -187,7 +177,7 @@ export class Label extends TextBase implements LabelDefinition {
|
||||
return zeroLength;
|
||||
}
|
||||
set [borderLeftWidthProperty.native](value: Length) {
|
||||
let nativeView = this._nativeView;
|
||||
let nativeView = this.nativeView;
|
||||
let border = nativeView.borderThickness;
|
||||
nativeView.borderThickness = {
|
||||
top: border.top,
|
||||
@@ -201,7 +191,7 @@ export class Label extends TextBase implements LabelDefinition {
|
||||
return zeroLength;
|
||||
}
|
||||
set [paddingTopProperty.native](value: Length) {
|
||||
let nativeView = this._nativeView;
|
||||
let nativeView = this.nativeView;
|
||||
let padding = nativeView.padding;
|
||||
nativeView.padding = {
|
||||
top: this.effectivePaddingTop,
|
||||
@@ -215,7 +205,7 @@ export class Label extends TextBase implements LabelDefinition {
|
||||
return zeroLength;
|
||||
}
|
||||
set [paddingRightProperty.native](value: Length) {
|
||||
let nativeView = this._nativeView;
|
||||
let nativeView = this.nativeView;
|
||||
let padding = nativeView.padding;
|
||||
nativeView.padding = {
|
||||
top: padding.top,
|
||||
@@ -229,7 +219,7 @@ export class Label extends TextBase implements LabelDefinition {
|
||||
return zeroLength;
|
||||
}
|
||||
set [paddingBottomProperty.native](value: Length) {
|
||||
let nativeView = this._nativeView;
|
||||
let nativeView = this.nativeView;
|
||||
let padding = nativeView.padding;
|
||||
nativeView.padding = {
|
||||
top: padding.top,
|
||||
@@ -243,7 +233,7 @@ export class Label extends TextBase implements LabelDefinition {
|
||||
return zeroLength;
|
||||
}
|
||||
set [paddingLeftProperty.native](value: Length) {
|
||||
let nativeView = this._nativeView;
|
||||
let nativeView = this.nativeView;
|
||||
let padding = nativeView.padding;
|
||||
nativeView.padding = {
|
||||
top: padding.top,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {
|
||||
SegmentedBarItemBase, SegmentedBarBase, selectedIndexProperty, itemsProperty, selectedBackgroundColorProperty,
|
||||
colorProperty, fontInternalProperty, fontSizeProperty, Color, Font, applyNativeSetters
|
||||
colorProperty, fontInternalProperty, fontSizeProperty, Color, Font, initNativeView
|
||||
} from "./segmented-bar-common";
|
||||
|
||||
export * from "./segmented-bar-common";
|
||||
@@ -64,7 +64,7 @@ export class SegmentedBarItem extends SegmentedBarItemBase {
|
||||
|
||||
this._textView = titleTextView;
|
||||
if (titleTextView) {
|
||||
applyNativeSetters(this);
|
||||
initNativeView(this);
|
||||
if (this.titleDirty) {
|
||||
this._update();
|
||||
}
|
||||
|
||||
@@ -3,166 +3,89 @@ import { ios as utilsIos } from "utils/utils";
|
||||
|
||||
export * from "./background-common";
|
||||
|
||||
interface NativeView extends UIView {
|
||||
hasNonUniformBorder: boolean;
|
||||
topBorderLayer: CAShapeLayer;
|
||||
rightBorderLayer: CAShapeLayer;
|
||||
bottomBorderLayer: CAShapeLayer;
|
||||
leftBorderLayer: CAShapeLayer;
|
||||
}
|
||||
|
||||
interface Rect {
|
||||
left: number;
|
||||
top: number;
|
||||
right: number;
|
||||
bottom: number;
|
||||
}
|
||||
|
||||
const clearCGColor = utilsIos.getter(UIColor, UIColor.clearColor).CGColor;
|
||||
|
||||
export module ios {
|
||||
export function createBackgroundUIColor(view: View, flip?: boolean): UIColor {
|
||||
let background = <Background>view.style.backgroundInternal;
|
||||
if (background.isEmpty()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let nativeView = view.nativeView;
|
||||
// Clip-path
|
||||
if (background.clipPath) {
|
||||
drawClipPath(nativeView, background);
|
||||
}
|
||||
|
||||
// Borders
|
||||
|
||||
// Clear all borders
|
||||
nativeView.layer.borderColor = undefined;
|
||||
nativeView.layer.borderWidth = 0;
|
||||
nativeView.layer.cornerRadius = 0;
|
||||
nativeView.clipsToBounds = true;
|
||||
|
||||
if (nativeView["topBorderLayer"]){
|
||||
(<CAShapeLayer>nativeView["topBorderLayer"]).removeFromSuperlayer();
|
||||
}
|
||||
|
||||
if (nativeView["rightBorderLayer"]){
|
||||
(<CAShapeLayer>nativeView["rightBorderLayer"]).removeFromSuperlayer();
|
||||
}
|
||||
|
||||
if (nativeView["bottomBorderLayer"]){
|
||||
(<CAShapeLayer>nativeView["bottomBorderLayer"]).removeFromSuperlayer();
|
||||
}
|
||||
|
||||
if (nativeView["leftBorderLayer"]){
|
||||
(<CAShapeLayer>nativeView["leftBorderLayer"]).removeFromSuperlayer();
|
||||
}
|
||||
|
||||
// Clip-path
|
||||
if (background.clipPath) {
|
||||
drawClipPath(nativeView, background);
|
||||
}
|
||||
const background = <Background>view.style.backgroundInternal;
|
||||
const nativeView = <NativeView>view.nativeView;
|
||||
|
||||
if (background.hasUniformBorder()) {
|
||||
let borderColor = background.getUniformBorderColor();
|
||||
if (borderColor && borderColor.ios){
|
||||
nativeView.layer.borderColor = borderColor.ios.CGColor;
|
||||
if (nativeView.hasNonUniformBorder) {
|
||||
clearNonUniformBorders(nativeView);
|
||||
}
|
||||
|
||||
const layer = nativeView.layer;
|
||||
const borderColor = background.getUniformBorderColor();
|
||||
layer.borderColor = !borderColor ? undefined : borderColor.ios.CGColor;
|
||||
layer.borderWidth = background.getUniformBorderWidth();
|
||||
layer.cornerRadius = background.getUniformBorderRadius();
|
||||
}
|
||||
else {
|
||||
nativeView.layer.borderColor = undefined;
|
||||
}
|
||||
nativeView.layer.borderWidth = background.getUniformBorderWidth();
|
||||
nativeView.layer.cornerRadius = background.getUniformBorderRadius();
|
||||
}
|
||||
else { // Draw non-uniform borders
|
||||
let nativeViewLayerBounds = {
|
||||
left: nativeView.layer.bounds.origin.x,
|
||||
top: nativeView.layer.bounds.origin.y,
|
||||
bottom: nativeView.layer.bounds.size.height,
|
||||
right: nativeView.layer.bounds.size.width
|
||||
};
|
||||
|
||||
let top = background.borderTopWidth;
|
||||
let right = background.borderRightWidth;
|
||||
let bottom = background.borderBottomWidth;
|
||||
let left = background.borderLeftWidth;
|
||||
|
||||
let lto: Point = {x: nativeViewLayerBounds.left, y: nativeViewLayerBounds.top};// left-top-outside
|
||||
let lti: Point = {x: nativeViewLayerBounds.left + left, y: nativeViewLayerBounds.top + top}; // left-top-inside
|
||||
|
||||
let rto: Point = {x: nativeViewLayerBounds.right, y: nativeViewLayerBounds.top}; // right-top-outside
|
||||
let rti: Point = {x: nativeViewLayerBounds.right - right, y: nativeViewLayerBounds.top + top}; // right-top-inside
|
||||
|
||||
let rbo: Point = {x: nativeViewLayerBounds.right, y: nativeViewLayerBounds.bottom}; // right-bottom-outside
|
||||
let rbi: Point = {x: nativeViewLayerBounds.right - right, y: nativeViewLayerBounds.bottom - bottom}; // right-bottom-inside
|
||||
|
||||
let lbo: Point = {x: nativeViewLayerBounds.left, y: nativeViewLayerBounds.bottom}; // left-bottom-outside
|
||||
let lbi: Point = {x: nativeViewLayerBounds.left + left, y: nativeViewLayerBounds.bottom - bottom}; // left-bottom-inside
|
||||
|
||||
if (top > 0 && background.borderTopColor && background.borderTopColor.ios){
|
||||
let topBorderPath = CGPathCreateMutable();
|
||||
CGPathMoveToPoint(topBorderPath, null, lto.x, lto.y);
|
||||
CGPathAddLineToPoint(topBorderPath, null, rto.x, rto.y);
|
||||
CGPathAddLineToPoint(topBorderPath, null, rti.x, rti.y);
|
||||
CGPathAddLineToPoint(topBorderPath, null, lti.x, lti.y);
|
||||
CGPathAddLineToPoint(topBorderPath, null, lto.x, lto.y);
|
||||
|
||||
let topBorderLayer = CAShapeLayer.layer();
|
||||
topBorderLayer.fillColor = background.borderTopColor.ios.CGColor;
|
||||
topBorderLayer.path = topBorderPath;
|
||||
|
||||
nativeView.layer.addSublayer(topBorderLayer);
|
||||
nativeView["topBorderLayer"] = topBorderLayer;
|
||||
drawNonUniformBorders(nativeView, background);
|
||||
}
|
||||
|
||||
if (right > 0 && background.borderRightColor && background.borderRightColor.ios){
|
||||
let rightBorderPath = CGPathCreateMutable();
|
||||
CGPathMoveToPoint(rightBorderPath, null, rto.x, rto.y);
|
||||
CGPathAddLineToPoint(rightBorderPath, null, rbo.x, rbo.y);
|
||||
CGPathAddLineToPoint(rightBorderPath, null, rbi.x, rbi.y);
|
||||
CGPathAddLineToPoint(rightBorderPath, null, rti.x, rti.y);
|
||||
CGPathAddLineToPoint(rightBorderPath, null, rto.x, rto.y);
|
||||
|
||||
let rightBorderLayer = CAShapeLayer.layer();
|
||||
rightBorderLayer.fillColor = background.borderRightColor.ios.CGColor;
|
||||
rightBorderLayer.path = rightBorderPath;
|
||||
|
||||
nativeView.layer.addSublayer(rightBorderLayer);
|
||||
nativeView["rightBorderLayer"] = rightBorderLayer;
|
||||
}
|
||||
|
||||
if (bottom > 0 && background.borderBottomColor && background.borderBottomColor.ios){
|
||||
let bottomBorderPath = CGPathCreateMutable();
|
||||
CGPathMoveToPoint(bottomBorderPath, null, rbo.x, rbo.y);
|
||||
CGPathAddLineToPoint(bottomBorderPath, null, lbo.x, lbo.y);
|
||||
CGPathAddLineToPoint(bottomBorderPath, null, lbi.x, lbi.y);
|
||||
CGPathAddLineToPoint(bottomBorderPath, null, rbi.x, rbi.y);
|
||||
CGPathAddLineToPoint(bottomBorderPath, null, rbo.x, rbo.y);
|
||||
|
||||
let bottomBorderLayer = CAShapeLayer.layer();
|
||||
bottomBorderLayer.fillColor = background.borderBottomColor.ios.CGColor;
|
||||
bottomBorderLayer.path = bottomBorderPath;
|
||||
|
||||
nativeView.layer.addSublayer(bottomBorderLayer);
|
||||
nativeView["bottomBorderLayer"] = bottomBorderLayer;
|
||||
}
|
||||
|
||||
if (left > 0 && background.borderLeftColor && background.borderLeftColor.ios){
|
||||
let leftBorderPath = CGPathCreateMutable();
|
||||
CGPathMoveToPoint(leftBorderPath, null, lbo.x, lbo.y);
|
||||
CGPathAddLineToPoint(leftBorderPath, null, lto.x, lto.y);
|
||||
CGPathAddLineToPoint(leftBorderPath, null, lti.x, lti.y);
|
||||
CGPathAddLineToPoint(leftBorderPath, null, lbi.x, lbi.y);
|
||||
CGPathAddLineToPoint(leftBorderPath, null, lbo.x, lbo.y);
|
||||
|
||||
let leftBorderLayer = CAShapeLayer.layer();
|
||||
leftBorderLayer.fillColor = background.borderLeftColor.ios.CGColor;
|
||||
leftBorderLayer.path = leftBorderPath;
|
||||
|
||||
nativeView.layer.addSublayer(leftBorderLayer);
|
||||
nativeView["leftBorderLayer"] = leftBorderLayer;
|
||||
}
|
||||
// Clip-path should be called after borders are applied.
|
||||
// It will eventually move them to different layer if uniform.
|
||||
if (background.clipPath) {
|
||||
drawClipPath(nativeView, background);
|
||||
}
|
||||
|
||||
if (!background.image) {
|
||||
return background.color ? background.color.ios : undefined;
|
||||
} else {
|
||||
return getUIColorFromImage(view, nativeView, background, flip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let frame = nativeView.frame;
|
||||
let boundsWidth = view.scaleX ? frame.size.width / view.scaleX : frame.size.width;
|
||||
let boundsHeight = view.scaleY ? frame.size.height / view.scaleY : frame.size.height;
|
||||
function clearNonUniformBorders(nativeView: NativeView): void {
|
||||
if (nativeView.topBorderLayer) {
|
||||
nativeView.topBorderLayer.removeFromSuperlayer();
|
||||
}
|
||||
|
||||
if (nativeView.rightBorderLayer) {
|
||||
nativeView.rightBorderLayer.removeFromSuperlayer();
|
||||
}
|
||||
|
||||
if (nativeView.bottomBorderLayer) {
|
||||
nativeView.bottomBorderLayer.removeFromSuperlayer();
|
||||
}
|
||||
|
||||
if (nativeView.leftBorderLayer) {
|
||||
nativeView.leftBorderLayer.removeFromSuperlayer();
|
||||
}
|
||||
}
|
||||
|
||||
function getUIColorFromImage(view: View, nativeView: UIView, background: Background, flip?: boolean): UIColor {
|
||||
const frame = nativeView.frame;
|
||||
const boundsWidth = view.scaleX ? frame.size.width / view.scaleX : frame.size.width;
|
||||
const boundsHeight = view.scaleY ? frame.size.height / view.scaleY : frame.size.height;
|
||||
if (!boundsWidth || !boundsHeight) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// We have an image for a background
|
||||
let img = <UIImage>background.image.ios;
|
||||
let params = background.getDrawParams(boundsWidth, boundsHeight);
|
||||
const params = background.getDrawParams(boundsWidth, boundsHeight);
|
||||
|
||||
if (params.sizeX > 0 && params.sizeY > 0) {
|
||||
let resizeRect = CGRectMake(0, 0, params.sizeX, params.sizeY);
|
||||
const resizeRect = CGRectMake(0, 0, params.sizeX, params.sizeY);
|
||||
UIGraphicsBeginImageContext(resizeRect.size);
|
||||
img.drawInRect(resizeRect);
|
||||
img = UIGraphicsGetImageFromCurrentImageContext();
|
||||
@@ -170,7 +93,7 @@ export module ios {
|
||||
}
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(CGSizeFromString(`{${boundsWidth},${boundsHeight}}`), false, 0.0);
|
||||
let context = UIGraphicsGetCurrentContext();
|
||||
const context = UIGraphicsGetCurrentContext();
|
||||
|
||||
if (background.color && background.color.ios) {
|
||||
CGContextSetFillColorWithColor(context, background.color.ios.CGColor);
|
||||
@@ -179,26 +102,25 @@ export module ios {
|
||||
|
||||
if (!params.repeatX && !params.repeatY) {
|
||||
img.drawAtPoint(CGPointMake(params.posX, params.posY));
|
||||
}
|
||||
else {
|
||||
let w = params.repeatX ? boundsWidth : img.size.width;
|
||||
let h = params.repeatY ? boundsHeight : img.size.height;
|
||||
} else {
|
||||
const w = params.repeatX ? boundsWidth : img.size.width;
|
||||
const h = params.repeatY ? boundsHeight : img.size.height;
|
||||
|
||||
CGContextSetPatternPhase(context, CGSizeMake(params.posX, params.posY));
|
||||
|
||||
params.posX = params.repeatX ? 0 : params.posX;
|
||||
params.posY = params.repeatY ? 0 : params.posY;
|
||||
|
||||
let patternRect = CGRectMake(params.posX, params.posY, w, h);
|
||||
const patternRect = CGRectMake(params.posX, params.posY, w, h);
|
||||
|
||||
img.drawAsPatternInRect(patternRect);
|
||||
}
|
||||
|
||||
let bkgImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
const bkgImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
if (flip) {
|
||||
let flippedImage = _flipImage(bkgImage);
|
||||
const flippedImage = _flipImage(bkgImage);
|
||||
return UIColor.alloc().initWithPatternImage(flippedImage);
|
||||
}
|
||||
|
||||
@@ -209,17 +131,16 @@ export module ios {
|
||||
// https://developer.apple.com/library/ios/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html
|
||||
function _flipImage(originalImage: UIImage): UIImage {
|
||||
UIGraphicsBeginImageContextWithOptions(originalImage.size, false, 0.0);
|
||||
let context = UIGraphicsGetCurrentContext();
|
||||
const context = UIGraphicsGetCurrentContext();
|
||||
CGContextSaveGState(context);
|
||||
CGContextTranslateCTM(context, 0.0, originalImage.size.height);
|
||||
CGContextScaleCTM(context, 1.0, -1.0);
|
||||
originalImage.drawInRect(CGRectMake(0, 0, originalImage.size.width, originalImage.size.height))
|
||||
CGContextRestoreGState(context);
|
||||
let flippedImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
const flippedImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
return flippedImage;
|
||||
}
|
||||
}
|
||||
|
||||
function cssValueToDevicePixels(source: string, total: number): number {
|
||||
let result;
|
||||
@@ -236,37 +157,206 @@ function cssValueToDevicePixels(source: string, total: number): number {
|
||||
return layout.toDevicePixels(result);
|
||||
}
|
||||
|
||||
function drawClipPath(nativeView: UIView, background: Background) {
|
||||
let path: any;
|
||||
function drawNonUniformBorders(nativeView: NativeView, background: Background) {
|
||||
const layer = nativeView.layer;
|
||||
layer.borderColor = undefined;
|
||||
layer.borderWidth = 0;
|
||||
layer.cornerRadius = 0;
|
||||
nativeView.clipsToBounds = true;
|
||||
|
||||
let bounds = {
|
||||
left: nativeView.bounds.origin.x,
|
||||
top: nativeView.bounds.origin.y,
|
||||
bottom: nativeView.bounds.size.height,
|
||||
right: nativeView.bounds.size.width
|
||||
const layerBounds = layer.bounds;
|
||||
const layerOrigin = layerBounds.origin;
|
||||
const layerSize = layerBounds.size;
|
||||
|
||||
const nativeViewLayerBounds = {
|
||||
left: layerOrigin.x,
|
||||
top: layerOrigin.y,
|
||||
bottom: layerSize.height,
|
||||
right: layerSize.width
|
||||
};
|
||||
|
||||
const top = background.borderTopWidth;
|
||||
const right = background.borderRightWidth;
|
||||
const bottom = background.borderBottomWidth;
|
||||
const left = background.borderLeftWidth;
|
||||
|
||||
const lto: Point = { x: nativeViewLayerBounds.left, y: nativeViewLayerBounds.top };// left-top-outside
|
||||
const lti: Point = { x: nativeViewLayerBounds.left + left, y: nativeViewLayerBounds.top + top }; // left-top-inside
|
||||
|
||||
const rto: Point = { x: nativeViewLayerBounds.right, y: nativeViewLayerBounds.top }; // right-top-outside
|
||||
const rti: Point = { x: nativeViewLayerBounds.right - right, y: nativeViewLayerBounds.top + top }; // right-top-inside
|
||||
|
||||
const rbo: Point = { x: nativeViewLayerBounds.right, y: nativeViewLayerBounds.bottom }; // right-bottom-outside
|
||||
const rbi: Point = { x: nativeViewLayerBounds.right - right, y: nativeViewLayerBounds.bottom - bottom }; // right-bottom-inside
|
||||
|
||||
const lbo: Point = { x: nativeViewLayerBounds.left, y: nativeViewLayerBounds.bottom }; // left-bottom-outside
|
||||
const lbi: Point = { x: nativeViewLayerBounds.left + left, y: nativeViewLayerBounds.bottom - bottom }; // left-bottom-inside
|
||||
|
||||
let hasNonUniformBorder: boolean;
|
||||
const borderTopColor = background.borderTopColor;
|
||||
if (top > 0 && borderTopColor && borderTopColor.ios) {
|
||||
const topBorderPath = CGPathCreateMutable();
|
||||
CGPathMoveToPoint(topBorderPath, null, lto.x, lto.y);
|
||||
CGPathAddLineToPoint(topBorderPath, null, rto.x, rto.y);
|
||||
CGPathAddLineToPoint(topBorderPath, null, rti.x, rti.y);
|
||||
CGPathAddLineToPoint(topBorderPath, null, lti.x, lti.y);
|
||||
CGPathAddLineToPoint(topBorderPath, null, lto.x, lto.y);
|
||||
|
||||
const topBorderLayer = CAShapeLayer.layer();
|
||||
topBorderLayer.fillColor = background.borderTopColor.ios.CGColor;
|
||||
topBorderLayer.path = topBorderPath;
|
||||
|
||||
layer.addSublayer(topBorderLayer);
|
||||
nativeView.topBorderLayer = topBorderLayer;
|
||||
hasNonUniformBorder = true;
|
||||
} else if (nativeView.topBorderLayer) {
|
||||
nativeView.topBorderLayer.removeFromSuperlayer();
|
||||
}
|
||||
|
||||
const borderRightColor = background.borderRightColor;
|
||||
if (right > 0 && borderRightColor && borderRightColor.ios) {
|
||||
const rightBorderPath = CGPathCreateMutable();
|
||||
CGPathMoveToPoint(rightBorderPath, null, rto.x, rto.y);
|
||||
CGPathAddLineToPoint(rightBorderPath, null, rbo.x, rbo.y);
|
||||
CGPathAddLineToPoint(rightBorderPath, null, rbi.x, rbi.y);
|
||||
CGPathAddLineToPoint(rightBorderPath, null, rti.x, rti.y);
|
||||
CGPathAddLineToPoint(rightBorderPath, null, rto.x, rto.y);
|
||||
|
||||
const rightBorderLayer = CAShapeLayer.layer();
|
||||
rightBorderLayer.fillColor = background.borderRightColor.ios.CGColor;
|
||||
rightBorderLayer.path = rightBorderPath;
|
||||
|
||||
layer.addSublayer(rightBorderLayer);
|
||||
nativeView.rightBorderLayer = rightBorderLayer;
|
||||
hasNonUniformBorder = true;
|
||||
} else if (nativeView.rightBorderLayer) {
|
||||
nativeView.rightBorderLayer.removeFromSuperlayer();
|
||||
}
|
||||
|
||||
const borderBottomColor = background.borderBottomColor;
|
||||
if (bottom > 0 && borderBottomColor && borderBottomColor.ios) {
|
||||
const bottomBorderPath = CGPathCreateMutable();
|
||||
CGPathMoveToPoint(bottomBorderPath, null, rbo.x, rbo.y);
|
||||
CGPathAddLineToPoint(bottomBorderPath, null, lbo.x, lbo.y);
|
||||
CGPathAddLineToPoint(bottomBorderPath, null, lbi.x, lbi.y);
|
||||
CGPathAddLineToPoint(bottomBorderPath, null, rbi.x, rbi.y);
|
||||
CGPathAddLineToPoint(bottomBorderPath, null, rbo.x, rbo.y);
|
||||
|
||||
const bottomBorderLayer = CAShapeLayer.layer();
|
||||
bottomBorderLayer.fillColor = background.borderBottomColor.ios.CGColor;
|
||||
bottomBorderLayer.path = bottomBorderPath;
|
||||
|
||||
layer.addSublayer(bottomBorderLayer);
|
||||
nativeView.bottomBorderLayer = bottomBorderLayer;
|
||||
hasNonUniformBorder = true;
|
||||
} else if (nativeView.bottomBorderLayer) {
|
||||
nativeView.bottomBorderLayer.removeFromSuperlayer();
|
||||
}
|
||||
|
||||
const borderLeftColor = background.borderLeftColor;
|
||||
if (left > 0 && borderLeftColor && borderLeftColor.ios) {
|
||||
const leftBorderPath = CGPathCreateMutable();
|
||||
CGPathMoveToPoint(leftBorderPath, null, lbo.x, lbo.y);
|
||||
CGPathAddLineToPoint(leftBorderPath, null, lto.x, lto.y);
|
||||
CGPathAddLineToPoint(leftBorderPath, null, lti.x, lti.y);
|
||||
CGPathAddLineToPoint(leftBorderPath, null, lbi.x, lbi.y);
|
||||
CGPathAddLineToPoint(leftBorderPath, null, lbo.x, lbo.y);
|
||||
|
||||
const leftBorderLayer = CAShapeLayer.layer();
|
||||
leftBorderLayer.fillColor = background.borderLeftColor.ios.CGColor;
|
||||
leftBorderLayer.path = leftBorderPath;
|
||||
|
||||
layer.addSublayer(leftBorderLayer);
|
||||
nativeView.leftBorderLayer = leftBorderLayer;
|
||||
hasNonUniformBorder = true;
|
||||
} else if (nativeView.leftBorderLayer) {
|
||||
nativeView.leftBorderLayer.removeFromSuperlayer();
|
||||
}
|
||||
|
||||
nativeView.hasNonUniformBorder = hasNonUniformBorder;
|
||||
}
|
||||
|
||||
function drawClipPath(nativeView: UIView, background: Background) {
|
||||
const layer = nativeView.layer;
|
||||
const layerBounds = layer.bounds;
|
||||
const layerOrigin = layerBounds.origin;
|
||||
const layerSize = layerBounds.size;
|
||||
|
||||
const bounds = {
|
||||
left: layerOrigin.x,
|
||||
top: layerOrigin.y,
|
||||
bottom: layerSize.height,
|
||||
right: layerSize.width
|
||||
};
|
||||
|
||||
if (bounds.right === 0 || bounds.bottom === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let clipPath = background.clipPath;
|
||||
let path: UIBezierPath;
|
||||
const clipPath = background.clipPath;
|
||||
|
||||
let functionName = clipPath.substring(0, clipPath.indexOf("("));
|
||||
let value = clipPath.replace(`${functionName}(`, "").replace(")", "");
|
||||
const functionName = clipPath.substring(0, clipPath.indexOf("("));
|
||||
const value = clipPath.replace(`${functionName}(`, "").replace(")", "");
|
||||
|
||||
if (functionName === "rect") {
|
||||
let arr = value.split(/[\s]+/);
|
||||
switch (functionName) {
|
||||
case "rect":
|
||||
path = rectPath(value, bounds);
|
||||
break;
|
||||
|
||||
let top = cssValueToDevicePixels(arr[0], bounds.top);
|
||||
let left = cssValueToDevicePixels(arr[1], bounds.left);
|
||||
let bottom = cssValueToDevicePixels(arr[2], bounds.bottom);
|
||||
let right = cssValueToDevicePixels(arr[3], bounds.right);
|
||||
case "inset":
|
||||
path = insetPath(value, bounds);
|
||||
break;
|
||||
|
||||
path = UIBezierPath.bezierPathWithRect(CGRectMake(left, top, right - left, bottom - top)).CGPath;
|
||||
case "circle":
|
||||
path = circlePath(value, bounds);
|
||||
break;
|
||||
|
||||
case "ellipse":
|
||||
path = ellipsePath(value, bounds);
|
||||
break;
|
||||
|
||||
case "polygon":
|
||||
path = polygonPath(value, bounds);
|
||||
break;
|
||||
}
|
||||
else if (functionName === "inset") {
|
||||
let arr = value.split(/[\s]+/);
|
||||
|
||||
if (path) {
|
||||
const shape = CAShapeLayer.layer();
|
||||
shape.path = path;
|
||||
layer.mask = shape;
|
||||
nativeView.clipsToBounds = true;
|
||||
|
||||
const borderWidth = background.getUniformBorderWidth();
|
||||
const borderColor = background.getUniformBorderColor();
|
||||
|
||||
if (borderWidth > 0 && borderColor instanceof Color) {
|
||||
const borderLayer = CAShapeLayer.layer();
|
||||
borderLayer.path = path;
|
||||
borderLayer.lineWidth = borderWidth * 2;
|
||||
borderLayer.strokeColor = borderColor.ios.CGColor;
|
||||
borderLayer.fillColor = clearCGColor;
|
||||
borderLayer.frame = nativeView.bounds;
|
||||
|
||||
layer.borderColor = undefined;
|
||||
layer.borderWidth = 0;
|
||||
layer.addSublayer(borderLayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function rectPath(value: string, bounds: Rect): UIBezierPath {
|
||||
const arr = value.split(/[\s]+/);
|
||||
const top = cssValueToDevicePixels(arr[0], bounds.top);
|
||||
const left = cssValueToDevicePixels(arr[1], bounds.left);
|
||||
const bottom = cssValueToDevicePixels(arr[2], bounds.bottom);
|
||||
const right = cssValueToDevicePixels(arr[3], bounds.right);
|
||||
|
||||
return UIBezierPath.bezierPathWithRect(CGRectMake(left, top, right - left, bottom - top)).CGPath;
|
||||
}
|
||||
|
||||
function insetPath(value: string, bounds: Rect): UIBezierPath {
|
||||
const arr = value.split(/[\s]+/);
|
||||
|
||||
let topString: string;
|
||||
let rightString: string;
|
||||
@@ -291,82 +381,59 @@ function drawClipPath(nativeView: UIView, background: Background) {
|
||||
leftString = arr[3];
|
||||
}
|
||||
|
||||
let top = cssValueToDevicePixels(topString, bounds.bottom);
|
||||
let right = cssValueToDevicePixels("100%", bounds.right) - cssValueToDevicePixels(rightString, bounds.right);
|
||||
let bottom = cssValueToDevicePixels("100%", bounds.bottom) - cssValueToDevicePixels(bottomString, bounds.bottom);
|
||||
let left = cssValueToDevicePixels(leftString, bounds.right);
|
||||
const top = cssValueToDevicePixels(topString, bounds.bottom);
|
||||
const right = cssValueToDevicePixels("100%", bounds.right) - cssValueToDevicePixels(rightString, bounds.right);
|
||||
const bottom = cssValueToDevicePixels("100%", bounds.bottom) - cssValueToDevicePixels(bottomString, bounds.bottom);
|
||||
const left = cssValueToDevicePixels(leftString, bounds.right);
|
||||
|
||||
path = UIBezierPath.bezierPathWithRect(CGRectMake(left, top, right - left, bottom - top)).CGPath;
|
||||
return UIBezierPath.bezierPathWithRect(CGRectMake(left, top, right - left, bottom - top)).CGPath;
|
||||
}
|
||||
else if (functionName === "circle") {
|
||||
let arr = value.split(/[\s]+/);
|
||||
|
||||
let radius = cssValueToDevicePixels(arr[0], (bounds.right > bounds.bottom ? bounds.bottom : bounds.right) / 2);
|
||||
let y = cssValueToDevicePixels(arr[2], bounds.bottom);
|
||||
let x = cssValueToDevicePixels(arr[3], bounds.right);
|
||||
|
||||
path = UIBezierPath.bezierPathWithArcCenterRadiusStartAngleEndAngleClockwise(CGPointMake(x, y), radius, 0, 360, true).CGPath;
|
||||
|
||||
} else if (functionName === "ellipse") {
|
||||
let arr = value.split(/[\s]+/);
|
||||
|
||||
let rX = cssValueToDevicePixels(arr[0], bounds.right);
|
||||
let rY = cssValueToDevicePixels(arr[1], bounds.bottom);
|
||||
let cX = cssValueToDevicePixels(arr[3], bounds.right);
|
||||
let cY = cssValueToDevicePixels(arr[4], bounds.bottom);
|
||||
|
||||
let left = cX - rX;
|
||||
let top = cY - rY;
|
||||
let width = rX * 2;
|
||||
let height = rY * 2;
|
||||
|
||||
path = UIBezierPath.bezierPathWithOvalInRect(CGRectMake(left, top, width, height)).CGPath;
|
||||
function circlePath(value: string, bounds: Rect): UIBezierPath {
|
||||
const arr = value.split(/[\s]+/);
|
||||
const radius = cssValueToDevicePixels(arr[0], (bounds.right > bounds.bottom ? bounds.bottom : bounds.right) / 2);
|
||||
const y = cssValueToDevicePixels(arr[2], bounds.bottom);
|
||||
const x = cssValueToDevicePixels(arr[3], bounds.right);
|
||||
|
||||
return UIBezierPath.bezierPathWithArcCenterRadiusStartAngleEndAngleClockwise(CGPointMake(x, y), radius, 0, 360, true).CGPath;
|
||||
}
|
||||
else if (functionName === "polygon") {
|
||||
|
||||
path = CGPathCreateMutable()
|
||||
function ellipsePath(value: string, bounds: Rect): UIBezierPath {
|
||||
const arr = value.split(/[\s]+/);
|
||||
|
||||
const rX = cssValueToDevicePixels(arr[0], bounds.right);
|
||||
const rY = cssValueToDevicePixels(arr[1], bounds.bottom);
|
||||
const cX = cssValueToDevicePixels(arr[3], bounds.right);
|
||||
const cY = cssValueToDevicePixels(arr[4], bounds.bottom);
|
||||
|
||||
const left = cX - rX;
|
||||
const top = cY - rY;
|
||||
const width = rX * 2;
|
||||
const height = rY * 2;
|
||||
|
||||
return UIBezierPath.bezierPathWithOvalInRect(CGRectMake(left, top, width, height)).CGPath;
|
||||
}
|
||||
|
||||
function polygonPath(value: string, bounds: Rect): UIBezierPath {
|
||||
const path = CGPathCreateMutable();
|
||||
|
||||
let firstPoint: Point;
|
||||
let arr = value.split(/[,]+/);
|
||||
const arr = value.split(/[,]+/);
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
let xy = arr[i].trim().split(/[\s]+/);
|
||||
let point: Point = {
|
||||
const xy = arr[i].trim().split(/[\s]+/);
|
||||
const point: Point = {
|
||||
x: cssValueToDevicePixels(xy[0], bounds.right),
|
||||
y: cssValueToDevicePixels(xy[1], bounds.bottom)
|
||||
};
|
||||
|
||||
if (!firstPoint) {
|
||||
firstPoint = point;
|
||||
CGPathMoveToPoint(path, null, point.x, point.y)
|
||||
CGPathMoveToPoint(path, null, point.x, point.y);
|
||||
}
|
||||
|
||||
CGPathAddLineToPoint(path, null, point.x, point.y)
|
||||
CGPathAddLineToPoint(path, null, point.x, point.y);
|
||||
}
|
||||
|
||||
CGPathAddLineToPoint(path, null, firstPoint.x, firstPoint.y)
|
||||
}
|
||||
|
||||
if (path) {
|
||||
let shape = CAShapeLayer.layer();
|
||||
shape.path = path;
|
||||
nativeView.layer.mask = shape;
|
||||
nativeView.clipsToBounds = true;
|
||||
|
||||
let borderWidth = background.getUniformBorderWidth();
|
||||
let borderColor = background.getUniformBorderColor();
|
||||
|
||||
if (borderWidth > 0 && borderColor instanceof Color){
|
||||
let borderLayer = CAShapeLayer.layer();
|
||||
borderLayer.path = path;
|
||||
borderLayer.lineWidth = borderWidth * 2;
|
||||
borderLayer.strokeColor = borderColor.ios.CGColor;
|
||||
borderLayer.fillColor = utilsIos.getter(UIColor, UIColor.clearColor).CGColor;
|
||||
borderLayer.frame = nativeView.bounds;
|
||||
|
||||
nativeView.layer.borderColor = undefined;
|
||||
nativeView.layer.borderWidth = 0;
|
||||
nativeView.layer.addSublayer(borderLayer);
|
||||
}
|
||||
}
|
||||
CGPathAddLineToPoint(path, null, firstPoint.x, firstPoint.y);
|
||||
return path;
|
||||
}
|
||||
@@ -3,8 +3,7 @@ import {
|
||||
tabTextColorProperty, tabBackgroundColorProperty, selectedTabTextColorProperty,
|
||||
androidSelectedTabHighlightColorProperty, androidOffscreenTabLimitProperty,
|
||||
fontSizeProperty, fontInternalProperty, View, layout, Color, Font,
|
||||
traceCategory, traceEnabled, traceWrite,
|
||||
applyNativeSetters
|
||||
traceCategory, traceEnabled, traceWrite, initNativeView
|
||||
} from "./tab-view-common"
|
||||
import { textTransformProperty, TextTransform, getTransformedText } from "ui/text-base";
|
||||
import { fromFileOrResource } from "image-source";
|
||||
@@ -25,7 +24,7 @@ export class TabViewItem extends TabViewItemBase {
|
||||
public setNativeView(textView: android.widget.TextView): void {
|
||||
this.nativeView = textView;
|
||||
if (textView) {
|
||||
applyNativeSetters(this);
|
||||
initNativeView(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,12 +20,7 @@ export class TextBase extends TextBaseCommon {
|
||||
|
||||
//Text
|
||||
get [textProperty.native](): string {
|
||||
let nativeView = this.nativeView;
|
||||
if (nativeView instanceof UIButton) {
|
||||
return nativeView.titleForState(UIControlState.Normal);
|
||||
} else {
|
||||
return nativeView.text;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
set [textProperty.native](value: string) {
|
||||
const newValue = (value === undefined || value === null) ? '' : value.toString();
|
||||
@@ -54,21 +49,22 @@ export class TextBase extends TextBaseCommon {
|
||||
}
|
||||
|
||||
//Color
|
||||
get [colorProperty.native](): Color {
|
||||
get [colorProperty.native](): UIColor {
|
||||
let nativeView = this.nativeView;
|
||||
if (nativeView instanceof UIButton) {
|
||||
return utils.ios.getColor(nativeView.titleColorForState(UIControlState.Normal));
|
||||
return nativeView.titleColorForState(UIControlState.Normal);
|
||||
} else {
|
||||
return utils.ios.getColor(nativeView.textColor);
|
||||
return nativeView.textColor;
|
||||
}
|
||||
}
|
||||
set [colorProperty.native](value: Color) {
|
||||
set [colorProperty.native](value: Color | UIColor) {
|
||||
const color = value instanceof Color ? value.ios : value;
|
||||
if (!this.formattedText) {
|
||||
let nativeView = this.nativeView;
|
||||
if (nativeView instanceof UIButton) {
|
||||
nativeView.setTitleColorForState(value.ios, UIControlState.Normal);
|
||||
nativeView.setTitleColorForState(color, UIControlState.Normal);
|
||||
} else {
|
||||
nativeView.textColor = value.ios;
|
||||
nativeView.textColor = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user