diff --git a/tns-core-modules/ui/action-bar/action-bar.ios.ts b/tns-core-modules/ui/action-bar/action-bar.ios.ts index fd94143f95..f5d74ebabd 100644 --- a/tns-core-modules/ui/action-bar/action-bar.ios.ts +++ b/tns-core-modules/ui/action-bar/action-bar.ios.ts @@ -232,24 +232,22 @@ export class ActionBar extends ActionBarBase { private _navigationBarHeight: number = 0; public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number) { - let width = layout.getMeasureSpecSize(widthMeasureSpec); - let widthMode = layout.getMeasureSpecMode(widthMeasureSpec); + const width = layout.getMeasureSpecSize(widthMeasureSpec); + const widthMode = layout.getMeasureSpecMode(widthMeasureSpec); - let height = layout.getMeasureSpecSize(heightMeasureSpec); - let heightMode = layout.getMeasureSpecMode(heightMeasureSpec); + const height = layout.getMeasureSpecSize(heightMeasureSpec); + const heightMode = layout.getMeasureSpecMode(heightMeasureSpec); let navBarWidth = 0; let navBarHeight = 0; - - let frame = this.page.frame; + + const frame = this.page.frame; if (frame) { let navBar: UIView = frame.ios.controller.navigationBar; if (!navBar.hidden) { - let navBarSize = navBar.sizeThatFits(CGSizeMake( - (widthMode === layout.UNSPECIFIED) ? Number.POSITIVE_INFINITY : width, - (heightMode === layout.UNSPECIFIED) ? Number.POSITIVE_INFINITY : height)); - navBarWidth = layout.toDevicePixels(navBarSize.width); - navBarHeight = layout.toDevicePixels(navBarSize.height); + const desiredSize = layout.measureNativeView(navBar, width, widthMode, height, heightMode); + navBarWidth = desiredSize.width; + navBarHeight = desiredSize.height; } } @@ -276,7 +274,7 @@ export class ActionBar extends ActionBarBase { View.layoutChild(this, this.titleView, 0, 0, right - left, this._navigationBarHeight); this.actionItems.getItems().forEach((actionItem) => { if (actionItem.actionView && actionItem.actionView.ios) { - let measuredWidth = actionItem.actionView.getMeasuredWidth();  + let measuredWidth = actionItem.actionView.getMeasuredWidth(); let measuredHeight = actionItem.actionView.getMeasuredHeight(); View.layoutChild(this, actionItem.actionView, 0, 0, measuredWidth, measuredHeight); } diff --git a/tns-core-modules/ui/core/view/view-common.ts b/tns-core-modules/ui/core/view/view-common.ts index 4c1d2927e4..b199a10e73 100644 --- a/tns-core-modules/ui/core/view/view-common.ts +++ b/tns-core-modules/ui/core/view/view-common.ts @@ -572,20 +572,14 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition { let measureHeight = 0; if (child && !child.isCollapsed) { - let width = layout.getMeasureSpecSize(widthMeasureSpec); - let widthMode = layout.getMeasureSpecMode(widthMeasureSpec); - - let height = layout.getMeasureSpecSize(heightMeasureSpec); - let heightMode = layout.getMeasureSpecMode(heightMeasureSpec); - child._updateEffectiveLayoutValues(parent); let style = child.style; let horizontalMargins = child.effectiveMarginLeft + child.effectiveMarginRight; let verticalMargins = child.effectiveMarginTop + child.effectiveMarginBottom; - let childWidthMeasureSpec = ViewCommon.getMeasureSpec(width, widthMode, horizontalMargins, child.effectiveWidth, style.horizontalAlignment === "stretch"); - let childHeightMeasureSpec = ViewCommon.getMeasureSpec(height, heightMode, verticalMargins, child.effectiveHeight, style.verticalAlignment === "stretch"); + let childWidthMeasureSpec = ViewCommon.getMeasureSpec(widthMeasureSpec, horizontalMargins, child.effectiveWidth, style.horizontalAlignment === "stretch"); + let childHeightMeasureSpec = ViewCommon.getMeasureSpec(heightMeasureSpec, verticalMargins, child.effectiveHeight, style.verticalAlignment === "stretch"); if (traceEnabled()) { traceWrite(child.parent + " :measureChild: " + child + " " + layout.measureSpecToString(childWidthMeasureSpec) + ", " + layout.measureSpecToString(childHeightMeasureSpec), traceCategories.Layout); @@ -599,7 +593,10 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition { return { measuredWidth: measureWidth, measuredHeight: measureHeight }; } - private static getMeasureSpec(parentLength: number, parentSpecMode: number, margins: number, childLength: number, stretched: boolean): number { + private static getMeasureSpec(parentSpec: number, margins: number, childLength: number, stretched: boolean): number { + const parentLength = layout.getMeasureSpecSize(parentSpec); + const parentSpecMode = layout.getMeasureSpecMode(parentSpec); + let resultSize: number; let resultMode: number; @@ -607,6 +604,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition { if (childLength >= 0) { // If mode !== UNSPECIFIED we take the smaller of parentLength and childLength // Otherwise we will need to clip the view but this is not possible in all Android API levels. + // TODO: remove Math.min(parentLength, childLength) resultSize = parentSpecMode === layout.UNSPECIFIED ? childLength : Math.min(parentLength, childLength); resultMode = layout.EXACTLY; } diff --git a/tns-core-modules/ui/core/view/view.android.ts b/tns-core-modules/ui/core/view/view.android.ts index 449f866b9a..f3e10fb52e 100644 --- a/tns-core-modules/ui/core/view/view.android.ts +++ b/tns-core-modules/ui/core/view/view.android.ts @@ -370,9 +370,9 @@ export class View extends ViewCommon { get [horizontalAlignmentProperty.native](): HorizontalAlignment { return org.nativescript.widgets.ViewHelper.getHorizontalAlignment(this.nativeView); } - set [horizontalAlignmentProperty.native](value: HorizontalAlignment)  { - const  nativeView = this.nativeView; - const  lp: any = nativeView.getLayoutParams() || new org.nativescript.widgets.CommonLayoutParams(); + set [horizontalAlignmentProperty.native](value: HorizontalAlignment) { + const nativeView = this.nativeView; + const lp: any = nativeView.getLayoutParams() || new org.nativescript.widgets.CommonLayoutParams(); // Set only if params gravity exists. if (lp.gravity !== undefined) { switch (value) { @@ -397,8 +397,8 @@ export class View extends ViewCommon { return org.nativescript.widgets.ViewHelper.getVerticalAlignment(this.nativeView); } set [verticalAlignmentProperty.native](value: VerticalAlignment) { - const  nativeView = this.nativeView; - const  lp: any = nativeView.getLayoutParams() || new org.nativescript.widgets.CommonLayoutParams(); + const nativeView = this.nativeView; + const lp: any = nativeView.getLayoutParams() || new org.nativescript.widgets.CommonLayoutParams(); // Set only if params gravity exists. if (lp.gravity !== undefined) { switch (value) { @@ -562,6 +562,7 @@ interface NativePercentLengthPropertyOptions { setPixels: NativeSetter; setPercent?: NativeSetter } + function createNativePercentLengthProperty(options: NativePercentLengthPropertyOptions) { const { key, auto = 0 } = options; let setPixels, getPixels, setPercent; @@ -590,11 +591,11 @@ function createNativePercentLengthProperty(options: NativePercentLengthPropertyO if (length == "auto") { // tslint:disable-line setPixels(this.nativeView, auto); } else if (typeof length === "number") { - setPixels(this.nativeView, Math.ceil(length * layout.getDisplayDensity())); + setPixels(this.nativeView, layout.round(layout.toDevicePixels(length))); } else if (length.unit == "dip") { // tslint:disable-line - setPixels(this.nativeView, Math.ceil(length.value * layout.getDisplayDensity())); + setPixels(this.nativeView, layout.round(layout.toDevicePixels(length.value))); } else if (length.unit == "px") { // tslint:disable-line - setPixels(this.nativeView, Math.ceil(length.value)); + setPixels(this.nativeView, layout.round(length.value)); } else if (length.unit == "%") { // tslint:disable-line setPercent(this.nativeView, length.value); } else { diff --git a/tns-core-modules/ui/core/view/view.ios.ts b/tns-core-modules/ui/core/view/view.ios.ts index 47840d388c..ae3a4aff12 100644 --- a/tns-core-modules/ui/core/view/view.ios.ts +++ b/tns-core-modules/ui/core/view/view.ios.ts @@ -3,8 +3,8 @@ import { Point, View as ViewDefinition } from "."; import { ios, Background } from "../../styling/background"; import { - ViewCommon, layout, isEnabledProperty, originXProperty, originYProperty, automationTextProperty, isUserInteractionEnabledProperty, - traceEnabled, traceWrite, traceCategories + ViewCommon, layout, isEnabledProperty, originXProperty, originYProperty, automationTextProperty, isUserInteractionEnabledProperty, + traceEnabled, traceWrite, traceCategories } from "./view-common"; import { @@ -100,35 +100,26 @@ export class View extends ViewCommon { } public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void { - let view = this.nativeView; - let nativeWidth = 0; - let nativeHeight = 0; - - let width = layout.getMeasureSpecSize(widthMeasureSpec); - let widthMode = layout.getMeasureSpecMode(widthMeasureSpec); + const view = this.nativeView; + const width = layout.getMeasureSpecSize(widthMeasureSpec); + const widthMode = layout.getMeasureSpecMode(widthMeasureSpec); - let height = layout.getMeasureSpecSize(heightMeasureSpec); - let heightMode = layout.getMeasureSpecMode(heightMeasureSpec); + const height = layout.getMeasureSpecSize(heightMeasureSpec); + const heightMode = layout.getMeasureSpecMode(heightMeasureSpec); + let nativeWidth = 0; + let nativeHeight = 0; if (view) { - if (widthMode === layout.UNSPECIFIED) { - width = Number.POSITIVE_INFINITY; - } - - if (heightMode === layout.UNSPECIFIED) { - height = Number.POSITIVE_INFINITY; - } - - let nativeSize = view.sizeThatFits(CGSizeMake(layout.toDeviceIndependentPixels(width), layout.toDeviceIndependentPixels(height))); - nativeWidth = layout.toDevicePixels(nativeSize.width); - nativeHeight = layout.toDevicePixels(nativeSize.height); + const nativeSize = layout.measureNativeView(view, width, widthMode, height, heightMode); + nativeWidth = nativeSize.width; + nativeHeight = nativeSize.height; } - let measureWidth = Math.max(nativeWidth, this.effectiveMinWidth); - let measureHeight = Math.max(nativeHeight, this.effectiveMinHeight); + const measureWidth = Math.max(nativeWidth, this.effectiveMinWidth); + const measureHeight = Math.max(nativeHeight, this.effectiveMinHeight); - let widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0); - let heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0); + const widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0); + const heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0); this.setMeasuredDimension(widthAndState, heightAndState); } diff --git a/tns-core-modules/ui/html-view/html-view.ios.ts b/tns-core-modules/ui/html-view/html-view.ios.ts index 1f59458bf2..efc4ee0605 100644 --- a/tns-core-modules/ui/html-view/html-view.ios.ts +++ b/tns-core-modules/ui/html-view/html-view.ios.ts @@ -1,5 +1,5 @@ import { - HtmlViewBase, View, layout, htmlProperty + HtmlViewBase, View, layout, htmlProperty } from "./html-view-common"; export * from "./html-view-common"; @@ -30,29 +30,20 @@ export class HtmlView extends HtmlViewBase { var nativeView = this._nativeView; if (nativeView) { - let width = layout.getMeasureSpecSize(widthMeasureSpec); - let widthMode = layout.getMeasureSpecMode(widthMeasureSpec); + const width = layout.getMeasureSpecSize(widthMeasureSpec); + const widthMode = layout.getMeasureSpecMode(widthMeasureSpec); - let height = layout.getMeasureSpecSize(heightMeasureSpec); - let heightMode = layout.getMeasureSpecMode(heightMeasureSpec); + const height = layout.getMeasureSpecSize(heightMeasureSpec); + const heightMode = layout.getMeasureSpecMode(heightMeasureSpec); - if (widthMode === layout.UNSPECIFIED) { - width = Number.POSITIVE_INFINITY; - } + const desiredSize = layout.measureNativeView(nativeView, width, widthMode, height, heightMode); - if (heightMode === layout.UNSPECIFIED) { - height = Number.POSITIVE_INFINITY; - } + const labelWidth = Math.min(desiredSize.width, width); + const measureWidth = Math.max(labelWidth, this.effectiveMinWidth); + const measureHeight = Math.max(desiredSize.height, this.effectiveMinHeight); - let nativeSize = nativeView.sizeThatFits(CGSizeMake(width, height)); - let labelWidth = layout.toDevicePixels(nativeSize.width); - - labelWidth = Math.min(labelWidth, width); - let measureWidth = Math.max(labelWidth, this.effectiveMinWidth); - let measureHeight = Math.max(layout.toDevicePixels(nativeSize.height), this.effectiveMinHeight); - - let widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0); - let heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0); + const widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0); + const heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0); this.setMeasuredDimension(widthAndState, heightAndState); } diff --git a/tns-core-modules/ui/label/label.ios.ts b/tns-core-modules/ui/label/label.ios.ts index b864c5a981..c7dd33b610 100644 --- a/tns-core-modules/ui/label/label.ios.ts +++ b/tns-core-modules/ui/label/label.ios.ts @@ -73,26 +73,18 @@ export class Label extends TextBase implements LabelDefinition { let height = layout.getMeasureSpecSize(heightMeasureSpec); let heightMode = layout.getMeasureSpecMode(heightMeasureSpec); - if (widthMode === layout.UNSPECIFIED) { - width = Number.POSITIVE_INFINITY; - } - - if (heightMode === layout.UNSPECIFIED) { - height = Number.POSITIVE_INFINITY; - } - this._fixedSize = (widthMode === layout.EXACTLY ? FixedSize.WIDTH : FixedSize.NONE) | (heightMode === layout.EXACTLY ? FixedSize.HEIGHT : FixedSize.NONE); - let nativeSize = nativeView.sizeThatFits(CGSizeMake(layout.toDeviceIndependentPixels(width), layout.toDeviceIndependentPixels(height))); - let labelWidth = layout.toDevicePixels(nativeSize.width); + const nativeSize = layout.measureNativeView(nativeView, width, widthMode, height, heightMode); + let labelWidth = nativeSize.width; if (this.textWrap) { labelWidth = Math.min(labelWidth, width); } let measureWidth = Math.max(labelWidth, this.effectiveMinWidth); - let measureHeight = Math.max(layout.toDevicePixels(nativeSize.height), this.effectiveMinHeight); + let measureHeight = Math.max(nativeSize.height, this.effectiveMinHeight); let widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0); let heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0); diff --git a/tns-core-modules/ui/page/page.ios.ts b/tns-core-modules/ui/page/page.ios.ts index 1cae90ea33..1face8b131 100644 --- a/tns-core-modules/ui/page/page.ios.ts +++ b/tns-core-modules/ui/page/page.ios.ts @@ -514,7 +514,7 @@ export class Page extends PageBase { if (!this._modalParent && this.frame && this.frame._getNavBarVisible(this)) { // Measure ActionBar with the full height. - let actionBarSize = View.measureChild(this, this.actionBar, widthMeasureSpec, heightMeasureSpec); + let actionBarSize = View.measureChild(this, this.actionBar, widthMeasureSpec, layout.makeMeasureSpec(height, layout.AT_MOST)); actionBarWidth = actionBarSize.measuredWidth; actionBarHeight = actionBarSize.measuredHeight; } diff --git a/tns-core-modules/ui/styling/background.ios.ts b/tns-core-modules/ui/styling/background.ios.ts index d32de6cb0e..ec4e1640fe 100644 --- a/tns-core-modules/ui/styling/background.ios.ts +++ b/tns-core-modules/ui/styling/background.ios.ts @@ -145,19 +145,15 @@ function _flipImage(originalImage: UIImage): UIImage { return flippedImage; } -function cssValueToDevicePixels(source: string, total: number): number { - let result; +function cssValueToDevicePixels(source: string, totalPx: number): number { source = source.trim(); - if (source.indexOf("px") !== -1) { - result = parseFloat(source.replace("px", "")); - } - else if (source.indexOf("%") !== -1 && total > 0) { - result = (parseFloat(source.replace("%", "")) / 100) * layout.toDeviceIndependentPixels(total); + return parseFloat(source.replace("px", "")); + } else if (source.indexOf("%") !== -1 && totalPx > 0) { + return (parseFloat(source.replace("%", "")) / 100) * totalPx; } else { - result = parseFloat(source); + return layout.toDevicePixels(parseFloat(source)); } - return layout.toDevicePixels(result); } function drawNonUniformBorders(nativeView: NativeView, background: Background) { @@ -293,10 +289,10 @@ function drawClipPath(nativeView: UIView, background: Background) { const layerSize = layerBounds.size; const bounds = { - left: layerOrigin.x, - top: layerOrigin.y, - bottom: layerSize.height, - right: layerSize.width + left: layout.toDevicePixels(layerOrigin.x), + top: layout.toDevicePixels(layerOrigin.y), + bottom: layout.toDevicePixels(layerSize.height), + right: layout.toDevicePixels(layerSize.width) }; if (bounds.right === 0 || bounds.bottom === 0) { diff --git a/tns-core-modules/ui/styling/style-properties.ts b/tns-core-modules/ui/styling/style-properties.ts index 8e9e8614c4..b2d16d2184 100644 --- a/tns-core-modules/ui/styling/style-properties.ts +++ b/tns-core-modules/ui/styling/style-properties.ts @@ -59,16 +59,16 @@ function toDevicePixelsCommon(length: PercentLength, auto: number, parentAvailab return auto; } if (typeof length === "number") { - return Math.ceil(layout.getDisplayDensity() * length); + return layout.round(layout.toDevicePixels(length)); } switch (length.unit) { case "px": - return Math.ceil(length.value); + return layout.round(length.value); case "%": - return Math.round(parentAvailableWidth * length.value); + return layout.round(parentAvailableWidth * length.value); case "dip": default: - return Math.ceil(layout.getDisplayDensity() * length.value); + return layout.round(layout.toDevicePixels(length.value)); } } diff --git a/tns-core-modules/ui/styling/style/style.d.ts b/tns-core-modules/ui/styling/style/style.d.ts index baf2cc0615..87f0219f97 100644 --- a/tns-core-modules/ui/styling/style/style.d.ts +++ b/tns-core-modules/ui/styling/style/style.d.ts @@ -134,14 +134,14 @@ export class Style extends Observable { public view: ViewBase; //flexbox layout properties - flexDirection: FlexDirection; - flexWrap: FlexWrap; - justifyContent: JustifyContent; - alignItems: AlignItems; - alignContent: AlignContent; - order: Order; - flexGrow: FlexGrow; - flexShrink: FlexShrink; - flexWrapBefore: FlexWrapBefore; - alignSelf: AlignSelf; + public flexDirection: FlexDirection; + public flexWrap: FlexWrap; + public justifyContent: JustifyContent; + public alignItems: AlignItems; + public alignContent: AlignContent; + public order: Order; + public flexGrow: FlexGrow; + public flexShrink: FlexShrink; + public flexWrapBefore: FlexWrapBefore; + public alignSelf: AlignSelf; } diff --git a/tns-core-modules/ui/styling/style/style.ts b/tns-core-modules/ui/styling/style/style.ts index b03d20ad2f..999dc5247d 100644 --- a/tns-core-modules/ui/styling/style/style.ts +++ b/tns-core-modules/ui/styling/style/style.ts @@ -17,9 +17,6 @@ export class Style extends Observable implements StyleDefinition { super(); } - // private _updateCounter = 0; - // private _nativeSetters = new Map(); - public fontInternal: Font; public backgroundInternal: Background; @@ -105,199 +102,15 @@ export class Style extends Observable implements StyleDefinition { public statusBarStyle: string; public androidStatusBarBackground: Color; - effectiveMinWidth: number; - effectiveMinHeight: number; - effectiveWidth: number; - effectiveHeight: number; - effectiveMarginTop: number; - effectiveMarginRight: number; - effectiveMarginBottom: number; - effectiveMarginLeft: number; - effectivePaddingTop: number; - effectivePaddingRight: number; - effectivePaddingBottom: number; - effectivePaddingLeft: number; - effectiveBorderTopWidth: number; - effectiveBorderRightWidth: number; - effectiveBorderBottomWidth: number; - effectiveBorderLeftWidth: number; - - flexDirection: FlexDirection; - flexWrap: FlexWrap; - justifyContent: JustifyContent; - alignItems: AlignItems; - alignContent: AlignContent; - order: Order; - flexGrow: FlexGrow; - flexShrink: FlexShrink; - flexWrapBefore: FlexWrapBefore; - alignSelf: AlignSelf; - - // public _updateTextDecoration() { - // if (this.textDecoration !== TextDecoration.none) { - // this._applyProperty(textDecorationProperty, this._getValue(textDecorationProperty)); - // } - // } - - // public _updateTextTransform() { - // if (this._getValue(textTransformProperty) !== TextTransform.none) { - // this._applyProperty(textTransformProperty, this._getValue(textTransformProperty)); - // } - // } - - // public _beginUpdate() { - // this._updateCounter++; - // } - - // public _endUpdate() { - // this._updateCounter--; - // if (this._updateCounter < 0) { - // throw new Error("style._endUpdate() called, but no update is in progress."); - // } - - // if (this._updateCounter === 0) { - // this._nativeSetters.forEach((newValue, property, map) => { this._applyStyleProperty(property, newValue); }); - // this._nativeSetters.clear(); - // } - // } - - // public _resetCssValues() { - // this.view._cancelAllAnimations(); - // resetStyleProperties(this); - // } - - // public _resetLocalValues() { - // this._resetValues(ValueSource.Local); - // } - - // public _inheritStyleProperties(parent: View) { - // parent.style._eachSetPropertyValue((property, value) => { - // if (property.inheritable) { - // // this._inheritStyleProperty(property, value); - // this._setValue(property, value, ValueSource.Inherited); - // } - - // return true; - // }); - // } - - // public _onPropertyChanged(property: Property, oldValue: any, newValue: any) { - // if (traceEnabled()) { - // traceWrite( - // "Style._onPropertyChanged view:" + this._view + - // ", property: " + property.name + - // ", oldValue: " + oldValue + - // ", newValue: " + newValue, traceCategories.Style); - // } - - // super._onPropertyChanged(property, oldValue, newValue); - - // this._view._checkMetadataOnPropertyChanged(property.metadata); - - // this._applyProperty(property, newValue); - // } - - // public _sizeChanged() { - // if (!this.backgroundInternal.isEmpty()) { - // this._applyStyleProperty(backgroundInternalProperty, this.backgroundInternal); - // } - - // let clipPathPropertyValue = this.clipPath; - // if (types.isString(clipPathPropertyValue) && clipPathPropertyValue !== "") { - // this._applyStyleProperty(clipPathProperty, clipPathPropertyValue); - // } - // } - - // public _syncNativeProperties() { - // this._eachSetPropertyValue((property, value) => { - // this._applyStyleProperty(property, value); - // return true; - // }); - // } - - // private _applyProperty(property: Property, newValue: any) { - // this._applyStyleProperty(property, newValue); - - // // The effective value of an inheritable property has changed - // // propagate the change down to the descendants to update their inherited properties. - // if (property.inheritable && this._view._childrenCount > 0) { - // this._view._eachChildView((child: View) => { - // // child.style._inheritStyleProperty(property); - // child.style._setValue(property, newValue, ValueSource.Inherited); - // return true; - // }); - // } - // } - - // private _applyStyleProperty(property: Property, newValue: any) { - // if (!this._view._shouldApplyStyleHandlers()) { - // return; - // } - - // if (this._updateCounter > 0) { - // this._nativeSetters.set(property, newValue); - // return; - // } - - // let handler: definition.StylePropertyChangedHandler = getHandler(property, this._view); - // if (!handler) { - // if (traceEnabled()) { - // traceWrite("No handler for property: " + property.name + " with id: " + property.id + ", view:" + this._view, traceCategories.Style); - // } - // } - // else { - // if (traceEnabled()) { - // traceWrite("Found handler for property: " + property.name + ", view:" + this._view, traceCategories.Style); - // } - - // let shouldReset = false; - // if (property.equalityComparer) { - // shouldReset = property.equalityComparer(newValue, property.defaultValue); - // } - // else { - // shouldReset = (newValue === property.defaultValue); - // } - - // public _updateTextDecoration() { - // if (this._getValue(textDecorationProperty) !== enums.TextDecoration.none) { - // this._applyProperty(textDecorationProperty, this._getValue(textDecorationProperty)); - // } - // } - - // this._view._onStylePropertyChanged(property); - // } - // } - - // get _nativeView(): any { - // return this._view._nativeView; - // } - - // private _setShorthandProperty(name: string, value: any): void { - // let pairs = styleProperty.getShorthandPairs(name, value); - // if (pairs) { - // this._beginUpdate(); - // for (let j = 0; j < pairs.length; j++) { - // let pair = pairs[j]; - // this._setValue(pair.property, pair.value, ValueSource.Local); - // } - // this._endUpdate(); - // } - // } -} - -Style.prototype.effectiveMinWidth = 0; -Style.prototype.effectiveMinHeight = 0; -Style.prototype.effectiveWidth = 0; -Style.prototype.effectiveHeight = 0; -Style.prototype.effectiveMarginTop = 0; -Style.prototype.effectiveMarginRight = 0; -Style.prototype.effectiveMarginBottom = 0; -Style.prototype.effectiveMarginLeft = 0; -Style.prototype.effectivePaddingTop = 0; -Style.prototype.effectivePaddingRight = 0; -Style.prototype.effectivePaddingBottom = 0; -Style.prototype.effectivePaddingLeft = 0; -Style.prototype.effectiveBorderTopWidth = 0; -Style.prototype.effectiveBorderRightWidth = 0; -Style.prototype.effectiveBorderBottomWidth = 0; -Style.prototype.effectiveBorderLeftWidth = 0; + //flexbox layout properties + public flexDirection: FlexDirection; + public flexWrap: FlexWrap; + public justifyContent: JustifyContent; + public alignItems: AlignItems; + public alignContent: AlignContent; + public order: Order; + public flexGrow: FlexGrow; + public flexShrink: FlexShrink; + public flexWrapBefore: FlexWrapBefore; + public alignSelf: AlignSelf; +} \ No newline at end of file diff --git a/tns-core-modules/ui/switch/switch.ios.ts b/tns-core-modules/ui/switch/switch.ios.ts index b5affcf8d8..9d4eae3ace 100644 --- a/tns-core-modules/ui/switch/switch.ios.ts +++ b/tns-core-modules/ui/switch/switch.ios.ts @@ -26,6 +26,7 @@ class SwitchChangeHandlerImpl extends NSObject { }; } +const zeroSize = { width: 0, height: 0 }; export class Switch extends SwitchBase { private _ios: UISwitch; private _handler: NSObject; @@ -52,12 +53,12 @@ export class Switch extends SwitchBase { public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void { // It can't be anything different from 51x31 - let nativeSize = this._nativeView.sizeThatFits(CGSizeMake(0, 0)); + let nativeSize = this._nativeView.sizeThatFits(zeroSize); this.width = nativeSize.width; this.height = nativeSize.height; - let widthAndState = layout.makeMeasureSpec(layout.toDevicePixels(nativeSize.width), layout.EXACTLY); - let heightAndState = layout.makeMeasureSpec(layout.toDevicePixels(nativeSize.height), layout.EXACTLY); + const widthAndState = Switch.resolveSizeAndState(layout.toDevicePixels(nativeSize.width), layout.toDevicePixels(51), layout.EXACTLY, 0); + const heightAndState = Switch.resolveSizeAndState(layout.toDevicePixels(nativeSize.height), layout.toDevicePixels(31), layout.EXACTLY, 0); this.setMeasuredDimension(widthAndState, heightAndState); } diff --git a/tns-core-modules/ui/tab-view/tab-view.ios.ts b/tns-core-modules/ui/tab-view/tab-view.ios.ts index 1463fa5cfe..abe8c07cd3 100644 --- a/tns-core-modules/ui/tab-view/tab-view.ios.ts +++ b/tns-core-modules/ui/tab-view/tab-view.ios.ts @@ -287,7 +287,7 @@ export class TabView extends TabViewBase { if (!iconSource) { return null; } - + let image: UIImage = this._iconsCache[iconSource]; if (!image) { const is = fromFileOrResource(iconSource); @@ -311,9 +311,9 @@ export class TabView extends TabViewBase { const height = layout.getMeasureSpecSize(heightMeasureSpec); const heightMode = layout.getMeasureSpecMode(heightMeasureSpec); - this._tabBarHeight = TabView.measureHelper(this._ios.tabBar, width, widthMode, height, heightMode).height; + this._tabBarHeight = layout.measureNativeView(this._ios.tabBar, width, widthMode, height, heightMode).height; const moreNavBarVisible = !!this._ios.moreNavigationController.navigationBar.window; - this._navBarHeight = moreNavBarVisible ? TabView.measureHelper(this._ios.moreNavigationController.navigationBar, width, widthMode, height, heightMode).height : 0; + this._navBarHeight = moreNavBarVisible ? layout.measureNativeView(this._ios.moreNavigationController.navigationBar, width, widthMode, height, heightMode).height : 0; const density = layout.getDisplayDensity(); let measureWidth = 0; @@ -347,13 +347,6 @@ export class TabView extends TabViewBase { } } - private static measureHelper(nativeView: UIView, width: number, widthMode: number, height: number, heightMode: number): CGSize { - const size = nativeView.sizeThatFits(CGSizeMake( - (widthMode === layout.UNSPECIFIED) ? Number.POSITIVE_INFINITY : width, - (heightMode === layout.UNSPECIFIED) ? Number.POSITIVE_INFINITY : height)); - return { width: layout.toDevicePixels(size.width), height: layout.toDevicePixels(size.height) }; - } - private _updateIOSTabBarColorsAndFonts(): void { if (!this.items) { return; @@ -460,7 +453,7 @@ interface TabStates { } function getTitleAttributesForStates(tabView: TabView): TabStates { - const result: TabStates = { }; + const result: TabStates = {}; const font = tabView.style.fontInternal.getUIFont(UIFont.systemFontOfSize(10)); let tabItemTextColor = tabView.style.tabTextColor; diff --git a/tns-core-modules/ui/text-base/text-base-common.ts b/tns-core-modules/ui/text-base/text-base-common.ts index 97b35f8993..da2a2c2d8a 100644 --- a/tns-core-modules/ui/text-base/text-base-common.ts +++ b/tns-core-modules/ui/text-base/text-base-common.ts @@ -245,6 +245,7 @@ export namespace WhiteSpace { export const whiteSpaceProperty = new CssProperty({ name: "whiteSpace", cssName: "white-space", + affectsLayout: isIOS, valueConverter: WhiteSpace.parse }); whiteSpaceProperty.register(Style); diff --git a/tns-core-modules/utils/utils-common.ts b/tns-core-modules/utils/utils-common.ts index ccfe03b796..ef8a8efd4f 100644 --- a/tns-core-modules/utils/utils-common.ts +++ b/tns-core-modules/utils/utils-common.ts @@ -87,6 +87,18 @@ export module layout { text += size; return text; } + + export function round(value: number): number { + const res = Math.floor(value + 0.5); + if (res !== 0) { + return res; + } else if (value === 0) { + return 0; + } else if (value > 0) { + return 1; + } + return -1; + } } export function isFileOrResourcePath(path: string): boolean { @@ -123,7 +135,7 @@ export function mergeSort(arr, compareFunc) { export function merge(left, right, compareFunc) { let result = []; - while(left.length && right.length) { + while (left.length && right.length) { if (compareFunc(left[0], right[0]) <= 0) { result.push(left.shift()); } else { diff --git a/tns-core-modules/utils/utils.android.ts b/tns-core-modules/utils/utils.android.ts index 7e890164de..25445e42b5 100644 --- a/tns-core-modules/utils/utils.android.ts +++ b/tns-core-modules/utils/utils.android.ts @@ -45,6 +45,15 @@ export module layout { export function toDeviceIndependentPixels(value: number): number { return value / getDisplayDensity(); } + + export function measureNativeView(nativeView: any /* android.view.View */, width: number, widthMode: number, height: number, heightMode: number): { width: number, height: number } { + const view = nativeView; + view.measure(makeMeasureSpec(width, widthMode), makeMeasureSpec(height, heightMode)); + return { + width: view.getMeasuredWidth(), + height: view.getMeasuredHeight() + }; + } } // We are using "ad" here to avoid namespace collision with the global android object diff --git a/tns-core-modules/utils/utils.d.ts b/tns-core-modules/utils/utils.d.ts index a0d2906ecf..a807817228 100644 --- a/tns-core-modules/utils/utils.d.ts +++ b/tns-core-modules/utils/utils.d.ts @@ -23,6 +23,9 @@ interface CacheLayerType { * Utility module related to layout. */ export module layout { + export type px = number; + export type dip = number; + /** * Bits that provide the actual measured size. */ @@ -53,7 +56,7 @@ export module layout { * @param size - The size component of measure specification. * @param mode - The mode component of measure specification. */ - export function makeMeasureSpec(size: number, mode: number): number; + export function makeMeasureSpec(px: number, mode: number): number; /** * Gets display density for the current device. */ @@ -62,13 +65,34 @@ export module layout { * Convert value to device pixels. * @param value - The pixel to convert. */ - export function toDevicePixels(value: number): number; + export function toDevicePixels(value: dip): px; /** * Convert value to device independent pixels. * @param value - The pixel to convert. */ - export function toDeviceIndependentPixels(value: number): number; + export function toDeviceIndependentPixels(value: px): dip; + /** + * Rounds value used in layout. + * @param value to round. + */ + export function round(px: px): px; + + /** + * Converts device pixels to device independent pixes and measure the nativeView. + * Returns the desired size of the nativeView in device pixels. + * @param nativeView the nativeView to measure (UIView or android.view.View) + * @param width the available width + * @param widthMode width mode - UNSPECIFIED, EXACTLY or AT_MOST + * @param height the available hegiht + * @param heightMode height mode - UNSPECIFIED, EXACTLY or AT_MOST + */ + export function measureNativeView(nativeView: any /* UIView or android.view.View */, width: number, widthMode: number, height: number, heightMode: number): { width: number, height: number }; + + /** + * Prints user friendly version of the measureSpec. + * @param measureSpec the spec to print + */ export function measureSpecToString(measureSpec: number): string; } diff --git a/tns-core-modules/utils/utils.ios.ts b/tns-core-modules/utils/utils.ios.ts index 42dcf5c747..1439ddca67 100644 --- a/tns-core-modules/utils/utils.ios.ts +++ b/tns-core-modules/utils/utils.ios.ts @@ -30,6 +30,18 @@ export module layout { export function toDeviceIndependentPixels(value: number): number { return value / mainScreenScale; } + + export function measureNativeView(nativeView: any /* UIView */, width: number, widthMode: number, height: number, heightMode: number): { width: number, height: number } { + const view = nativeView; + const nativeSize = view.sizeThatFits({ + width: widthMode === 0 /* layout.UNSPECIFIED */ ? Number.POSITIVE_INFINITY : toDeviceIndependentPixels(width), + height: heightMode === 0 /* layout.UNSPECIFIED */ ? Number.POSITIVE_INFINITY : toDeviceIndependentPixels(height) + }); + + nativeSize.width = toDevicePixels(nativeSize.width); + nativeSize.height = toDevicePixels(nativeSize.height); + return nativeSize; + } } export module ios {