import application = require("application"); import styling = require("ui/styling"); import types = require("utils/types"); import trace = require("trace"); import {DependencyObservable, PropertyMetadata, PropertyMetadataSettings, PropertyChangeData, Property, ValueSource, NativeValueResult} from "ui/core/dependency-observable"; import {View} from "ui/core/view"; import {Color} from "color"; import styleProperty = require("ui/styling/style-property"); import converters = require("./converters"); import enums = require("ui/enums"); import utils = require("utils/utils"); import font = require("ui/styling/font"); import background = require("ui/styling/background"); import platform = require("platform"); import definition = require("ui/styling/style"); import * as imageSourceModule from "image-source"; var imageSource: typeof imageSourceModule; function ensureImageSource() { if (!imageSource) { imageSource = require("image-source"); } } // key is the property id and value is Dictionary; var _registeredHandlers = Array(); // key is a className + property id and value is StylePropertyChangedHandler; var _handlersCache = {}; // classes like Frame that does not need to handle styling properties. var noStylingClasses = {}; // on Android we explicitly set propertySettings to None because android will invalidate its layout (skip unnecessary native call). var AffectsLayout = platform.device.os === platform.platformNames.android ? PropertyMetadataSettings.None : PropertyMetadataSettings.AffectsLayout; interface ThicknessValue { left: Object; top: Object; right: Object; bottom: Object; } interface PercentHelper { value: number; isPercent: boolean; isError: boolean; } function parseMargin(value: any): ThicknessValue { if (types.isString(value)) { let arr = (value).split(/[ ,]+/); let top: Object; let right: Object; let bottom: Object; let left: Object; if (arr.length === 1) { top = right = bottom = left = arr[0]; } else if (arr.length === 2) { top = bottom = arr[0]; right = left = arr[1]; } else if (arr.length === 4) { top = arr[0]; right = arr[1]; bottom = arr[2]; left = arr[3]; } else { throw new Error("Invalid value for margin: " + value); } return { top: top, right: right, bottom: bottom, left: left } } else if (types.isNumber(value)) { return { top: value, right: value, bottom: value, left: value } } else { return value; } } function parseThickness(value: any): definition.Thickness { var result: definition.Thickness = { top: 0, right: 0, bottom: 0, left: 0 }; if (types.isString(value)) { var arr = value.split(/[ ,]+/); var top = parseInt(arr[0]); top = isNaN(top) ? 0 : top; var right = parseInt(arr[1]); right = isNaN(right) ? top : right; var bottom = parseInt(arr[2]); bottom = isNaN(bottom) ? top : bottom; var left = parseInt(arr[3]); left = isNaN(left) ? right : left; result.top = top; result.right = right; result.bottom = bottom; result.left = left; } else if (types.isNumber(value)) { result.top = result.right = result.bottom = result.left = value; } else { result = value; } return result; } function layoutParamsComparer(x: definition.CommonLayoutParams, y: definition.CommonLayoutParams): boolean { return x.width === y.width && x.height === y.height && x.leftMargin === y.leftMargin && x.topMargin === y.topMargin && x.rightMargin === y.rightMargin && x.bottomMargin === y.bottomMargin && x.horizontalAlignment === y.horizontalAlignment && x.verticalAlignment === y.verticalAlignment && x.widthPercent === y.widthPercent && x.heightPercent === y.heightPercent && x.leftMarginPercent === y.leftMarginPercent && x.topMarginPercent === y.topMarginPercent && x.rightMarginPercent === y.rightMarginPercent && x.bottomMarginPercent === y.bottomMarginPercent } function onLayoutParamsChanged(data: PropertyChangeData) { let style =