Skip to content

Commit 526df1a

Browse files
committed
Impl corner radius and click target support for WinUIBackend
Also updated the `.cornerRadius` modifier's implementation to not update the corner radius in dry-run updates.
1 parent 57ede1e commit 526df1a

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

Sources/SwiftCrossUI/Modifiers/CornerRadius.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ struct CornerRadiusModifier<Content: View>: View {
5454
backend: backend,
5555
dryRun: dryRun
5656
)
57-
backend.setCornerRadius(of: widget, to: cornerRadius)
57+
if !dryRun {
58+
backend.setCornerRadius(of: widget, to: cornerRadius)
59+
}
5860
return contentResult
5961
}
6062
}

Sources/WinUIBackend/WinUIBackend.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,28 @@ public final class WinUIBackend: AppBackend {
281281
canvas.background = brush
282282
}
283283

284+
public func setCornerRadius(of widget: Widget, to radius: Int) {
285+
let visual: WinAppSDK.Visual = try! widget.getVisualInternal()
286+
287+
let geometry = try! visual.compositor.createRoundedRectangleGeometry()!
288+
geometry.cornerRadius = WindowsFoundation.Vector2(
289+
x: Float(radius),
290+
y: Float(radius)
291+
)
292+
293+
// We assume that SwiftCrossUI has explicitly set the size of the
294+
// underlying widget.
295+
geometry.size = WindowsFoundation.Vector2(
296+
x: Float(widget.width),
297+
y: Float(widget.height)
298+
)
299+
300+
let clip = try! visual.compositor.createGeometricClip()!
301+
clip.geometry = geometry
302+
303+
visual.clip = clip
304+
}
305+
284306
public func naturalSize(of widget: Widget) -> SIMD2<Int> {
285307
let allocation = WindowsFoundation.Size(
286308
width: .infinity,
@@ -823,6 +845,37 @@ public final class WinUIBackend: AppBackend {
823845
}
824846
}
825847

848+
public func createClickTarget(wrapping child: Widget) -> Widget {
849+
let clickTarget = ClickTarget()
850+
addChild(child, to: clickTarget)
851+
clickTarget.child = child
852+
853+
// Set a background so that the click target's entire area gets hit
854+
// tested. The background we set is transparent so that it doesn't
855+
// change the visual appearance of the view.
856+
let brush = SolidColorBrush()
857+
brush.color = UWP.Color(a: 0, r: 0, g: 0, b: 0)
858+
clickTarget.background = brush
859+
860+
clickTarget.pointerPressed.addHandler { [weak clickTarget] _, _ in
861+
guard let clickTarget else {
862+
return
863+
}
864+
clickTarget.clickHandler?()
865+
}
866+
return clickTarget
867+
}
868+
869+
public func updateClickTarget(
870+
_ clickTarget: Widget,
871+
clickHandler handleClick: @escaping () -> Void
872+
) {
873+
let clickTarget = clickTarget as! ClickTarget
874+
clickTarget.clickHandler = handleClick
875+
clickTarget.width = clickTarget.child!.width
876+
clickTarget.height = clickTarget.child!.height
877+
}
878+
826879
// public func createTable(rows: Int, columns: Int) -> Widget {
827880
// let grid = Grid()
828881
// grid.columnSpacing = 10
@@ -943,3 +996,8 @@ final class CustomComboBox: ComboBox {
943996
final class CustomSplitView: SplitView {
944997
var sidebarResizeHandler: (() -> Void)?
945998
}
999+
1000+
final class ClickTarget: WinUI.Canvas {
1001+
var clickHandler: (() -> Void)?
1002+
var child: WinUI.FrameworkElement?
1003+
}

0 commit comments

Comments
 (0)