import { ControlStateChangeListener } from '../core/control-state-change'; import { ButtonBase } from './button-common'; import { View, PseudoClassHandler } from '../core/view'; import { backgroundColorProperty, borderTopWidthProperty, borderRightWidthProperty, borderBottomWidthProperty, borderLeftWidthProperty, paddingLeftProperty, paddingTopProperty, paddingRightProperty, paddingBottomProperty } from '../styling/style-properties'; import { textAlignmentProperty, whiteSpaceProperty } from '../text-base'; import { layout } from '../../utils'; import { CoreTypes } from '../../core-types'; import { Color } from '../../color'; export * from './button-common'; export class Button extends ButtonBase { public nativeViewProtected: UIButton; private _tapHandler: NSObject; private _stateChangedHandler: ControlStateChangeListener; createNativeView() { return UIButton.buttonWithType(UIButtonType.System); } public initNativeView(): void { super.initNativeView(); const nativeView = this.nativeViewProtected; this._tapHandler = TapHandlerImpl.initWithOwner(new WeakRef(this)); nativeView.addTargetActionForControlEvents(this._tapHandler, 'tap', UIControlEvents.TouchUpInside); } public disposeNativeView(): void { this._tapHandler = null; super.disposeNativeView(); } // @ts-ignore get ios() { return this.nativeViewProtected; } public onUnloaded() { super.onUnloaded(); if (this._stateChangedHandler) { this._stateChangedHandler.stop(); } } @PseudoClassHandler('normal', 'highlighted', 'pressed', 'active') _updateButtonStateChangeHandler(subscribe: boolean) { if (subscribe) { if (!this._stateChangedHandler) { this._stateChangedHandler = new ControlStateChangeListener(this.nativeViewProtected, (s: string) => { this._goToVisualState(s); }); } this._stateChangedHandler.start(); } else { this._stateChangedHandler.stop(); } } [backgroundColorProperty.getDefault](): UIColor { return this.nativeViewProtected.backgroundColor; } [backgroundColorProperty.setNative](value: UIColor | Color) { this.nativeViewProtected.backgroundColor = value instanceof Color ? value.ios : value; } [borderTopWidthProperty.getDefault](): CoreTypes.LengthType { return { value: this.nativeViewProtected.contentEdgeInsets.top, unit: 'px', }; } [borderTopWidthProperty.setNative](value: CoreTypes.LengthType) { const inset = this.nativeViewProtected.contentEdgeInsets; const top = layout.toDeviceIndependentPixels(this.effectivePaddingTop + this.effectiveBorderTopWidth); this.nativeViewProtected.contentEdgeInsets = { top: top, left: inset.left, bottom: inset.bottom, right: inset.right, }; } [borderRightWidthProperty.getDefault](): CoreTypes.LengthType { return { value: this.nativeViewProtected.contentEdgeInsets.right, unit: 'px', }; } [borderRightWidthProperty.setNative](value: CoreTypes.LengthType) { const inset = this.nativeViewProtected.contentEdgeInsets; const right = layout.toDeviceIndependentPixels(this.effectivePaddingRight + this.effectiveBorderRightWidth); this.nativeViewProtected.contentEdgeInsets = { top: inset.top, left: inset.left, bottom: inset.bottom, right: right, }; } [borderBottomWidthProperty.getDefault](): CoreTypes.LengthType { return { value: this.nativeViewProtected.contentEdgeInsets.bottom, unit: 'px', }; } [borderBottomWidthProperty.setNative](value: CoreTypes.LengthType) { const inset = this.nativeViewProtected.contentEdgeInsets; const bottom = layout.toDeviceIndependentPixels(this.effectivePaddingBottom + this.effectiveBorderBottomWidth); this.nativeViewProtected.contentEdgeInsets = { top: inset.top, left: inset.left, bottom: bottom, right: inset.right, }; } [borderLeftWidthProperty.getDefault](): CoreTypes.LengthType { return { value: this.nativeViewProtected.contentEdgeInsets.left, unit: 'px', }; } [borderLeftWidthProperty.setNative](value: CoreTypes.LengthType) { const inset = this.nativeViewProtected.contentEdgeInsets; const left = layout.toDeviceIndependentPixels(this.effectivePaddingLeft + this.effectiveBorderLeftWidth); this.nativeViewProtected.contentEdgeInsets = { top: inset.top, left: left, bottom: inset.bottom, right: inset.right, }; } [paddingTopProperty.getDefault](): CoreTypes.LengthType { return { value: this.nativeViewProtected.contentEdgeInsets.top, unit: 'px', }; } [paddingTopProperty.setNative](value: CoreTypes.LengthType) { const inset = this.nativeViewProtected.contentEdgeInsets; const top = layout.toDeviceIndependentPixels(this.effectivePaddingTop + this.effectiveBorderTopWidth); this.nativeViewProtected.contentEdgeInsets = { top: top, left: inset.left, bottom: inset.bottom, right: inset.right, }; } [paddingRightProperty.getDefault](): CoreTypes.LengthType { return { value: this.nativeViewProtected.contentEdgeInsets.right, unit: 'px', }; } [paddingRightProperty.setNative](value: CoreTypes.LengthType) { const inset = this.nativeViewProtected.contentEdgeInsets; const right = layout.toDeviceIndependentPixels(this.effectivePaddingRight + this.effectiveBorderRightWidth); this.nativeViewProtected.contentEdgeInsets = { top: inset.top, left: inset.left, bottom: inset.bottom, right: right, }; } [paddingBottomProperty.getDefault](): CoreTypes.LengthType { return { value: this.nativeViewProtected.contentEdgeInsets.bottom, unit: 'px', }; } [paddingBottomProperty.setNative](value: CoreTypes.LengthType) { const inset = this.nativeViewProtected.contentEdgeInsets; const bottom = layout.toDeviceIndependentPixels(this.effectivePaddingBottom + this.effectiveBorderBottomWidth); this.nativeViewProtected.contentEdgeInsets = { top: inset.top, left: inset.left, bottom: bottom, right: inset.right, }; } [paddingLeftProperty.getDefault](): CoreTypes.LengthType { return { value: this.nativeViewProtected.contentEdgeInsets.left, unit: 'px', }; } [paddingLeftProperty.setNative](value: CoreTypes.LengthType) { const inset = this.nativeViewProtected.contentEdgeInsets; const left = layout.toDeviceIndependentPixels(this.effectivePaddingLeft + this.effectiveBorderLeftWidth); this.nativeViewProtected.contentEdgeInsets = { top: inset.top, left: left, bottom: inset.bottom, right: inset.right, }; } [textAlignmentProperty.setNative](value: CoreTypes.TextAlignmentType) { switch (value) { case 'left': this.nativeViewProtected.titleLabel.textAlignment = NSTextAlignment.Left; this.nativeViewProtected.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left; break; case 'initial': case 'center': this.nativeViewProtected.titleLabel.textAlignment = NSTextAlignment.Center; this.nativeViewProtected.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Center; break; case 'right': this.nativeViewProtected.titleLabel.textAlignment = NSTextAlignment.Right; this.nativeViewProtected.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Right; break; } } [whiteSpaceProperty.setNative](value: CoreTypes.WhiteSpaceType) { const nativeView = this.nativeViewProtected.titleLabel; switch (value) { case 'normal': nativeView.lineBreakMode = NSLineBreakMode.ByWordWrapping; nativeView.numberOfLines = 0; break; case 'nowrap': case 'initial': nativeView.lineBreakMode = NSLineBreakMode.ByTruncatingMiddle; nativeView.numberOfLines = 1; break; } } public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void { // If there is text-wrap UIButton.sizeThatFits will return wrong result (not respecting the text wrap). // So fallback to original onMeasure if there is no text-wrap and use custom measure otherwise. if (!this.textWrap) { return super.onMeasure(widthMeasureSpec, heightMeasureSpec); } const nativeView = this.nativeViewProtected; if (nativeView) { const width = layout.getMeasureSpecSize(widthMeasureSpec); const widthMode = layout.getMeasureSpecMode(widthMeasureSpec); const height = layout.getMeasureSpecSize(heightMeasureSpec); const heightMode = layout.getMeasureSpecMode(heightMeasureSpec); const horizontalPadding = this.effectivePaddingLeft + this.effectiveBorderLeftWidth + this.effectivePaddingRight + this.effectiveBorderRightWidth; let verticalPadding = this.effectivePaddingTop + this.effectiveBorderTopWidth + this.effectivePaddingBottom + this.effectiveBorderBottomWidth; // The default button padding for UIButton - 6dip top and bottom. if (verticalPadding === 0) { verticalPadding = layout.toDevicePixels(12); } const desiredSize = layout.measureNativeView(nativeView.titleLabel, width - horizontalPadding, widthMode, height - verticalPadding, heightMode); desiredSize.width = desiredSize.width + horizontalPadding; desiredSize.height = desiredSize.height + verticalPadding; const measureWidth = Math.max(desiredSize.width, this.effectiveMinWidth); const measureHeight = Math.max(desiredSize.height, this.effectiveMinHeight); const widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0); const heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0); this.setMeasuredDimension(widthAndState, heightAndState); } } } @NativeClass class TapHandlerImpl extends NSObject { private _owner: WeakRef