diff --git a/example-app-ios/KiteUI Example App.xcodeproj/xcuserdata/jivie.xcuserdatad/xcschemes/KiteUI Example App.xcscheme b/example-app-ios/KiteUI Example App.xcodeproj/xcuserdata/jivie.xcuserdatad/xcschemes/KiteUI Example App.xcscheme new file mode 100644 index 000000000..ecca8a98d --- /dev/null +++ b/example-app-ios/KiteUI Example App.xcodeproj/xcuserdata/jivie.xcuserdatad/xcschemes/KiteUI Example App.xcscheme @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example-app-ios/KiteUI Example App/Assets.xcassets/imagesGraph126.imageset/Contents.json b/example-app-ios/KiteUI Example App/Assets.xcassets/imagesGraph126.imageset/Contents.json new file mode 100644 index 000000000..e1eb2486c --- /dev/null +++ b/example-app-ios/KiteUI Example App/Assets.xcassets/imagesGraph126.imageset/Contents.json @@ -0,0 +1,10 @@ +{ + "info": { "version": 1, "author": "xcode" }, + "images": [ + { + "filename": "graph_126.png", + "scale": "1x", + "idiom": "universal" + } + ] +} \ No newline at end of file diff --git a/example-app-ios/KiteUI Example App/Assets.xcassets/imagesGraph126.imageset/graph_126.png b/example-app-ios/KiteUI Example App/Assets.xcassets/imagesGraph126.imageset/graph_126.png new file mode 100644 index 000000000..f722e1f75 Binary files /dev/null and b/example-app-ios/KiteUI Example App/Assets.xcassets/imagesGraph126.imageset/graph_126.png differ diff --git a/example-app/src/androidMain/res/drawable-xhdpi/images_graph126.png b/example-app/src/androidMain/res/drawable-xhdpi/images_graph126.png new file mode 100644 index 000000000..f722e1f75 Binary files /dev/null and b/example-app/src/androidMain/res/drawable-xhdpi/images_graph126.png differ diff --git a/example-app/src/commonMain/kotlin/com/lightningkite/mppexampleapp/App.kt b/example-app/src/commonMain/kotlin/com/lightningkite/mppexampleapp/App.kt index 8a070389e..e2e543786 100644 --- a/example-app/src/commonMain/kotlin/com/lightningkite/mppexampleapp/App.kt +++ b/example-app/src/commonMain/kotlin/com/lightningkite/mppexampleapp/App.kt @@ -8,6 +8,7 @@ import com.lightningkite.kiteui.navigation.mainScreenNavigator import com.lightningkite.kiteui.reactive.* import com.lightningkite.kiteui.views.* import com.lightningkite.kiteui.views.l2.* +import com.lightningkite.mppexampleapp.internal.RootScreen import kotlin.math.absoluteValue import kotlin.time.Duration.Companion.seconds @@ -22,6 +23,7 @@ fun ViewWriter.app(navigator: ScreenNavigator, dialog: ScreenNavigator) { ::navItems { listOf( NavLink(title = { "Home" }, icon = { Icon.home }) { { HomeScreen() } }, + NavLink(title = { "Internal" }, icon = { Icon.home }) { { RootScreen } }, NavLink(title = { "Documentation" }, icon = { Icon.list }) { { DocSearchScreen } }, ) } diff --git a/example-app/src/iosMain/kotlin/com/lightningkite/mppexampleapp/App.ios.kt b/example-app/src/iosMain/kotlin/com/lightningkite/mppexampleapp/App.ios.kt index e1d914a0e..1ab199085 100644 --- a/example-app/src/iosMain/kotlin/com/lightningkite/mppexampleapp/App.ios.kt +++ b/example-app/src/iosMain/kotlin/com/lightningkite/mppexampleapp/App.ios.kt @@ -1,9 +1,11 @@ package com.lightningkite.mppexampleapp +import com.lightningkite.kiteui.models.remMultiplier import com.lightningkite.kiteui.navigation.ScreenNavigator import com.lightningkite.kiteui.views.setup import platform.UIKit.UIViewController fun root(viewController: UIViewController) { + remMultiplier = 1.0 viewController.setup(appTheme) { app(ScreenNavigator { AutoRoutes }, ScreenNavigator { AutoRoutes }) } } \ No newline at end of file diff --git a/example-app/src/iosMain/kotlin/com/lightningkite/mppexampleapp/widgets/Code.ios.kt b/example-app/src/iosMain/kotlin/com/lightningkite/mppexampleapp/widgets/Code.ios.kt index fac7259bb..c5dc7dff9 100644 --- a/example-app/src/iosMain/kotlin/com/lightningkite/mppexampleapp/widgets/Code.ios.kt +++ b/example-app/src/iosMain/kotlin/com/lightningkite/mppexampleapp/widgets/Code.ios.kt @@ -112,8 +112,8 @@ actual class Code actual constructor(context: RContext) : RView(context) { } override fun applyForeground(theme: Theme) { - fontAndStyle = theme.font actualNative.foreground = theme.foreground + fontAndStyle = theme.font // // sizeConstraints = SizeConstraints( diff --git a/library/src/iosMain/kotlin/com/lightningkite/kiteui/models/data.kt b/library/src/iosMain/kotlin/com/lightningkite/kiteui/models/data.kt index 595e5a6f1..e0bce9d4f 100644 --- a/library/src/iosMain/kotlin/com/lightningkite/kiteui/models/data.kt +++ b/library/src/iosMain/kotlin/com/lightningkite/kiteui/models/data.kt @@ -15,7 +15,7 @@ actual typealias DimensionRaw = Double @Suppress("NOTHING_TO_INLINE") actual inline val Int.px: Dimension get() = Dimension(this.toDouble() / UIScreen.mainScreen.scale) -var remMultiplier: Double = 0.75 +var remMultiplier: Double = 1.0 @Suppress("NOTHING_TO_INLINE") actual inline val Int.rem: Dimension get() = Dimension(this.toDouble() * UIFont.systemFontSize * remMultiplier) diff --git a/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/RView.ios.kt b/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/RView.ios.kt index 939d30300..e0bd4a3a5 100644 --- a/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/RView.ios.kt +++ b/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/RView.ios.kt @@ -8,6 +8,7 @@ import com.lightningkite.kiteui.reactive.AppState import com.lightningkite.kiteui.views.direct.WrapperView import kotlinx.cinterop.useContents import platform.CoreGraphics.CGPointMake +import platform.CoreGraphics.CGRectMake import platform.CoreGraphics.CGSizeMake import platform.Foundation.NSNumber import platform.Foundation.numberWithFloat @@ -15,6 +16,7 @@ import platform.QuartzCore.CATransaction import platform.QuartzCore.kCAGradientLayerAxial import platform.QuartzCore.kCAGradientLayerRadial import platform.UIKit.UIColor +import platform.UIKit.UIScrollView import platform.UIKit.UIView import kotlin.experimental.ExperimentalNativeApi import kotlin.math.PI @@ -222,7 +224,10 @@ actual abstract class RView actual constructor(context: RContext) : RViewHelper( parentSpacing = this@RView.parentSpacing.value desiredCornerRadius = theme.cornerRadii - matchParentSize("insert") + val bounds = this@RView.native.layerSize() + + frame = bounds + refreshCorners() } } } diff --git a/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/LinearLayout.kt b/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/LinearLayout.kt index a5b45d002..9fad4d45d 100644 --- a/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/LinearLayout.kt +++ b/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/LinearLayout.kt @@ -87,6 +87,9 @@ class LinearLayout : UIView(CGRectZero.readValue()), UIViewWithSizeOverridesProt val UIView.secondaryAlign get() = if (horizontal) extensionVerticalAlign else extensionHorizontalAlign override fun sizeThatFits(size: CValue): CValue { + if(subviews.any { it == viewDebugTarget?.native }) { + println("parent sizeThatFits: ${size.useContents { "$width x $height" }}") + } val sizeLocal = size.local val measuredSize = Size() @@ -212,6 +215,9 @@ class LinearLayout : UIView(CGRectZero.readValue()), UIViewWithSizeOverridesProt var lastLaidOutSize: Size? = null override fun layoutSubviews() { + if(subviews.any { it == viewDebugTarget?.native }) { + println("parent layoutSubviews: ${bounds.useContents { "${size.width} x ${size.height}" }}") + } val mySize = bounds.useContents { size.local } if (lastLaidOutSize == mySize) return var t = PerformanceInfo.trace("layoutLinear") diff --git a/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/TextView.ios.kt b/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/TextView.ios.kt index dd2f41bf1..86763930d 100644 --- a/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/TextView.ios.kt +++ b/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/TextView.ios.kt @@ -124,8 +124,8 @@ actual class TextView actual constructor(context: RContext) : RView(context) { } override fun applyForeground(theme: Theme) { - fontAndStyle = theme.font native.foreground = theme.foreground + fontAndStyle = theme.font // // sizeConstraints = SizeConstraints( @@ -165,12 +165,3 @@ fun preferredScaleFactor() = if (ENABLE_DYNAMIC_TYPE) { } else { 1.0 } - -fun UILabel.updateFont() { - val textSize = extensionTextSize ?: return - val alignment = textAlignment - font = extensionFontAndStyle?.let { - it.font.get(textSize * preferredScaleFactor(), it.weight.toUIFontWeight(), it.italic) - } ?: UIFont.systemFontOfSize(textSize) - textAlignment = alignment -} \ No newline at end of file diff --git a/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/UILabelWithGradient.kt b/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/UILabelWithGradient.kt index ceb17ff90..2d651fad6 100644 --- a/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/UILabelWithGradient.kt +++ b/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/UILabelWithGradient.kt @@ -83,6 +83,8 @@ class UILabelWithGradient : UIView(CGRectZero.readValue()) { ) } return label.sizeThatFits(smallerSize).useContents { + if(com.lightningkite.kiteui.viewDebugTarget?.native == this@UILabelWithGradient) + println("Size that fits on text: $width, $height") CGSizeMake( width = width + padding * 2, height = height.coerceAtLeast(label.font.lineHeight) + padding * 2, diff --git a/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/modifiers.ios.kt b/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/modifiers.ios.kt index ca17a8c7d..3eebe7a70 100644 --- a/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/modifiers.ios.kt +++ b/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/modifiers.ios.kt @@ -15,6 +15,8 @@ import com.lightningkite.kiteui.reactive.invoke import com.lightningkite.kiteui.reactive.reactiveScope import com.lightningkite.kiteui.views.* import kotlinx.cinterop.* +import platform.QuartzCore.CALayer +import platform.CoreGraphics.CGRectMake import platform.UIKit.UILongPressGestureRecognizer import platform.UIKit.UITapGestureRecognizer import platform.darwin.NSObject diff --git a/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/sizeThatFits2.kt b/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/sizeThatFits2.kt index 66bb0fb65..8797f883c 100644 --- a/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/sizeThatFits2.kt +++ b/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/direct/sizeThatFits2.kt @@ -23,8 +23,8 @@ fun UIView.sizeThatFits2( it.maxHeight?.let { h = h.coerceAtMost(it.value) } it.minWidth?.let { w = w.coerceAtLeast(it.value) } it.minHeight?.let { h = h.coerceAtLeast(it.value) } - it.width?.let { w = it.value } - it.height?.let { h = it.value } + it.width?.let { w = it.value.coerceAtMost(w) } + it.height?.let { h = it.value.coerceAtMost(h) } CGSizeMake(w, h) } ?: size val measured = when (this) { diff --git a/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/styling.ios.kt b/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/styling.ios.kt index 44b9dddc3..3b675511d 100644 --- a/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/styling.ios.kt +++ b/library/src/iosMain/kotlin/com/lightningkite/kiteui/views/styling.ios.kt @@ -4,7 +4,9 @@ import com.lightningkite.kiteui.models.* import com.lightningkite.kiteui.objc.toObjcId import com.lightningkite.kiteui.reactive.await import com.lightningkite.kiteui.reactive.reactiveScope +import com.lightningkite.kiteui.views.RView import kotlinx.cinterop.BetaInteropApi +import kotlinx.cinterop.CValue import kotlinx.cinterop.ExperimentalForeignApi import kotlinx.cinterop.useContents import platform.CoreGraphics.* @@ -12,6 +14,7 @@ import platform.QuartzCore.* import platform.UIKit.UIColor import platform.UIKit.UIImageView import platform.UIKit.UIView +import platform.UIKit.UIScrollView import kotlin.math.min import kotlin.time.DurationUnit import platform.Foundation.* @@ -24,14 +27,6 @@ fun Color.toUiColor(): UIColor = UIColor( ) - -@Suppress("NOTHING_TO_INLINE") -internal inline fun CALayer.matchParentSize(context: String) { - superlayer?.bounds?.let { - frame = it - } -} - @Suppress("NOTHING_TO_INLINE") internal inline fun UIView.layoutSubviewsAndLayers() { // Fixes a really cursed crash where "this" is null due to GC interactions @@ -42,32 +37,50 @@ internal inline fun UIView.layoutSubviewsAndLayers() { } } +internal fun UIView.layerSize(): CValue { + val n = this + val bounds = if(n is UIScrollView) n.contentSize.useContents { + val cs = this + n.bounds.useContents { + val b = this + CGRectMake(0.0, 0.0, cs.width + b.size.width, cs.height + b.size.height) + } + } else n.bounds + return bounds +} + internal fun UIView.layoutLayers() { + val bounds = layerSize() layer?.sublayers?.forEach { it as CALayer - if(it is CAGradientLayerResizing) { - it.matchParentSize("layoutSubviewsAndLayers") + if (it is CAGradientLayerResizing) { + it.frame = bounds it.refreshCorners() } } } + internal fun UIView.layoutLayers(parentSpacing: Double) { + val bounds = layerSize() layer?.sublayers?.forEach { it as CALayer - if(it is CAGradientLayerResizing) { + if (it is CAGradientLayerResizing) { it.parentSpacing = parentSpacing - it.matchParentSize("layoutSubviewsAndLayers") + it.frame = bounds it.refreshCorners() } } } -class CAGradientLayerResizing: CAGradientLayer { +class CAGradientLayerResizing : CAGradientLayer { - @OverrideInit constructor():super() - @OverrideInit constructor(coder: platform.Foundation.NSCoder):super(coder) - @OverrideInit constructor(layer: kotlin.Any):super(layer) + @OverrideInit + constructor() : super() + @OverrideInit + constructor(coder: platform.Foundation.NSCoder) : super(coder) + @OverrideInit + constructor(layer: kotlin.Any) : super(layer) private var backgroundMask: CALayer? = null @@ -99,7 +112,7 @@ class CAGradientLayerResizing: CAGradientLayer { } fun refreshCorners() { - val v = when(val d = desiredCornerRadius) { + val v = when (val d = desiredCornerRadius) { is CornerRadii.Constant -> d.value.value.coerceAtMost(parentSpacing).coerceAtMost(bounds.useContents { min(size.width, size.height) / 2 }) is CornerRadii.ForceConstant -> d.value.value.coerceAtMost(bounds.useContents { min(size.width, size.height) / 2 }) is CornerRadii.RatioOfSize -> d.ratio * bounds.useContents { min(size.width, size.height) }