diff --git a/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/EmptyExampleSchemaWidgetFactory.kt b/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/EmptyExampleSchemaWidgetFactory.kt index 12962bd3f1..b73616c01a 100644 --- a/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/EmptyExampleSchemaWidgetFactory.kt +++ b/redwood-protocol-widget/src/commonTest/kotlin/app/cash/redwood/protocol/widget/EmptyExampleSchemaWidgetFactory.kt @@ -18,6 +18,7 @@ package app.cash.redwood.protocol.widget import app.cash.redwood.Modifier import com.example.redwood.testing.widget.Button import com.example.redwood.testing.widget.Button2 +import com.example.redwood.testing.widget.Rectangle import com.example.redwood.testing.widget.ScopedTestRow import com.example.redwood.testing.widget.TestRow import com.example.redwood.testing.widget.TestSchemaWidgetFactory @@ -39,4 +40,5 @@ open class EmptyTestSchemaWidgetFactory : TestSchemaWidgetFactory { } override fun Button2(): Button2 = TODO() override fun TextInput(): TextInput = TODO() + override fun Rectangle(): Rectangle = TODO() } diff --git a/test-app/android-views/src/main/kotlin/com/example/redwood/testing/android/views/AndroidTestSchemaWidgetFactory.kt b/test-app/android-views/src/main/kotlin/com/example/redwood/testing/android/views/AndroidTestSchemaWidgetFactory.kt index b425304709..4a1752cf6a 100644 --- a/test-app/android-views/src/main/kotlin/com/example/redwood/testing/android/views/AndroidTestSchemaWidgetFactory.kt +++ b/test-app/android-views/src/main/kotlin/com/example/redwood/testing/android/views/AndroidTestSchemaWidgetFactory.kt @@ -20,6 +20,7 @@ import android.view.View import android.widget.Button as ButtonWidget import android.widget.TextView import com.example.redwood.testing.widget.Button +import com.example.redwood.testing.widget.Rectangle import com.example.redwood.testing.widget.TestSchemaWidgetFactory import com.example.redwood.testing.widget.Text @@ -32,4 +33,5 @@ class AndroidTestSchemaWidgetFactory( override fun Button(): Button = ViewButton(ButtonWidget(context)) override fun Button2() = TODO() override fun TextInput() = TODO() + override fun Rectangle(): Rectangle = ViewRectangle(context) } diff --git a/test-app/android-views/src/main/kotlin/com/example/redwood/testing/android/views/ViewRectangle.kt b/test-app/android-views/src/main/kotlin/com/example/redwood/testing/android/views/ViewRectangle.kt new file mode 100644 index 0000000000..276c9c7ef2 --- /dev/null +++ b/test-app/android-views/src/main/kotlin/com/example/redwood/testing/android/views/ViewRectangle.kt @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2023 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.example.redwood.testing.android.views + +import android.content.Context +import android.graphics.drawable.GradientDrawable +import android.view.View +import app.cash.redwood.Modifier +import app.cash.redwood.ui.Density +import app.cash.redwood.ui.Dp +import com.example.redwood.testing.widget.Rectangle + +internal class ViewRectangle( + context: Context, +) : Rectangle { + + private val density = Density(context.resources) + + val background = GradientDrawable() + + override val value = View(context) + + override var modifier: Modifier = Modifier + init { + value.background = background + } + override fun backgroundColor(backgroundColor: UInt) { + background.setColor(backgroundColor.toInt()) + } + + override fun cornerRadius(cornerRadius: Float) { + background.cornerRadius = with(density) { Dp(cornerRadius.toDouble()).toPx() }.toFloat() + } +} diff --git a/test-app/browser/src/commonMain/kotlin/com/example/redwood/testing/browser/widgetFactory.kt b/test-app/browser/src/commonMain/kotlin/com/example/redwood/testing/browser/widgetFactory.kt index 4ae3446561..97cc2f9221 100644 --- a/test-app/browser/src/commonMain/kotlin/com/example/redwood/testing/browser/widgetFactory.kt +++ b/test-app/browser/src/commonMain/kotlin/com/example/redwood/testing/browser/widgetFactory.kt @@ -37,6 +37,9 @@ class HtmlWidgetFactory( } override fun TextInput() = TODO() + + override fun Rectangle() = TODO() + override fun Button2() = TODO() override fun ScopedTestRow() = throw UnsupportedOperationException() diff --git a/test-app/ios-uikit/TestApp.xcodeproj/project.pbxproj b/test-app/ios-uikit/TestApp.xcodeproj/project.pbxproj index 47135d3742..67aeaedfc7 100644 --- a/test-app/ios-uikit/TestApp.xcodeproj/project.pbxproj +++ b/test-app/ios-uikit/TestApp.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 635661DA21F12B7E00DD7240 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 635661D821F12B7E00DD7240 /* Main.storyboard */; }; 635661DC21F12B8000DD7240 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 635661DB21F12B8000DD7240 /* Assets.xcassets */; }; 635661DF21F12B8000DD7240 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 635661DD21F12B8000DD7240 /* LaunchScreen.storyboard */; }; + 96C741A32ACCAB13007C41FE /* RectangleBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C741A22ACCAB13007C41FE /* RectangleBinding.swift */; }; CB85C0B725AFE61A007A2CC7 /* TestAppViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB85C0B625AFE61A007A2CC7 /* TestAppViewController.swift */; }; CB9E3E822AB379C4007A87CD /* ButtonBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB9E3E812AB379C4007A87CD /* ButtonBinding.swift */; }; CB9F76562810A8A8008CF457 /* IosHostApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB9F76552810A8A8008CF457 /* IosHostApi.swift */; }; @@ -28,6 +29,7 @@ 635661DE21F12B8000DD7240 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 635661E021F12B8000DD7240 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 63E90CF521FEBBB700449E04 /* main.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = main.framework; path = "../ios-shared/build/xcode-frameworks/main.framework"; sourceTree = ""; }; + 96C741A22ACCAB13007C41FE /* RectangleBinding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RectangleBinding.swift; sourceTree = ""; }; CB85C0B625AFE61A007A2CC7 /* TestAppViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestAppViewController.swift; sourceTree = ""; }; CB9E3E812AB379C4007A87CD /* ButtonBinding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonBinding.swift; sourceTree = ""; }; CB9F76552810A8A8008CF457 /* IosHostApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IosHostApi.swift; sourceTree = ""; }; @@ -74,6 +76,7 @@ 10AA3D4B28C03D32006F125E /* IosTestSchemaWidgetFactory.swift */, 10AA3D4D28C0EA40006F125E /* TextBinding.swift */, CB9E3E812AB379C4007A87CD /* ButtonBinding.swift */, + 96C741A22ACCAB13007C41FE /* RectangleBinding.swift */, ); path = TestApp; sourceTree = ""; @@ -173,6 +176,7 @@ files = ( 10AA3D4C28C03D32006F125E /* IosTestSchemaWidgetFactory.swift in Sources */, CB9E3E822AB379C4007A87CD /* ButtonBinding.swift in Sources */, + 96C741A32ACCAB13007C41FE /* RectangleBinding.swift in Sources */, CB85C0B725AFE61A007A2CC7 /* TestAppViewController.swift in Sources */, 10AA3D4E28C0EA40006F125E /* TextBinding.swift in Sources */, 635661D521F12B7E00DD7240 /* AppDelegate.swift in Sources */, diff --git a/test-app/ios-uikit/TestApp/IosTestSchemaWidgetFactory.swift b/test-app/ios-uikit/TestApp/IosTestSchemaWidgetFactory.swift index 851e118f5b..7a25383379 100644 --- a/test-app/ios-uikit/TestApp/IosTestSchemaWidgetFactory.swift +++ b/test-app/ios-uikit/TestApp/IosTestSchemaWidgetFactory.swift @@ -31,15 +31,19 @@ class IosTestSchemaWidgetFactory: TestSchemaWidgetFactory { func Button() -> Button { return ButtonBinding() } - + func Button2() -> Button2 { fatalError() } - + + func Rectangle() -> Rectangle { + return RectangleBinding() + } + func ScopedTestRow() -> ScopedTestRow { fatalError() } - + func TestRow() -> TestRow { fatalError() } diff --git a/test-app/ios-uikit/TestApp/RectangleBinding.swift b/test-app/ios-uikit/TestApp/RectangleBinding.swift new file mode 100644 index 0000000000..09b931c70f --- /dev/null +++ b/test-app/ios-uikit/TestApp/RectangleBinding.swift @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2023 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import Foundation +import TestAppKt +import UIKit + +class RectangleBinding: Rectangle { + + private let root: UIView = { + let view = UIView() + return view + }() + + var modifier: Modifier = ExposedKt.modifier() + var value: Any { root } + + func backgroundColor(backgroundColor: UInt32) { + root.backgroundColor = UIColor(argb: UInt(backgroundColor)) + } + + func cornerRadius(cornerRadius: Float) { + root.layer.cornerRadius = CGFloat(cornerRadius) + } +} + +private extension UIColor { + convenience init(argb: UInt) { + let alpha = CGFloat((argb >> 24) & 0xFF) / 255.0 + let red = CGFloat((argb >> 16) & 0xFF) / 255.0 + let green = CGFloat((argb >> 8) & 0xFF) / 255.0 + let blue = CGFloat(argb & 0xFF) / 255.0 + + self.init(red: red, green: green, blue: blue, alpha: alpha) + } +} diff --git a/test-app/schema/src/main/kotlin/com/example/redwood/testing/schema.kt b/test-app/schema/src/main/kotlin/com/example/redwood/testing/schema.kt index 849624800d..da41d44f92 100644 --- a/test-app/schema/src/main/kotlin/com/example/redwood/testing/schema.kt +++ b/test-app/schema/src/main/kotlin/com/example/redwood/testing/schema.kt @@ -40,6 +40,7 @@ import kotlin.time.Duration Button::class, Button2::class, TextInput::class, + Rectangle::class, ], dependencies = [ Dependency(1, RedwoodLayout::class), @@ -95,6 +96,15 @@ public data class TextInput( @Property(5) val maxLength: Int, ) +@Widget(8) +public data class Rectangle( + /** expects argb format: 0xAARRGGBBu*/ + @Property(1) val backgroundColor: UInt, + + @Default("0f") + @Property(2) val cornerRadius: Float, +) + public object TestScope public object SecondaryTestScope