Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow gtk modifiers to be expressed as css attributes. #345

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 30 additions & 13 deletions Sources/TokamakGTK/Modifiers/LayoutModifiers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@ import CGTK
import TokamakCore

extension _FrameLayout: WidgetModifier {
public func modify(widget: UnsafeMutablePointer<GtkWidget>) {
func modify(widget: UnsafeMutablePointer<GtkWidget>) {
gtk_widget_set_size_request(widget, Int32(width ?? -1), Int32(height ?? -1))
// gtk_widget_set_halign(widget, alignment.horizontal.gtkValue)
// gtk_widget_set_valign(widget, alignment.vertical.gtkValue)
}
}

extension _FlexFrameLayout: WidgetModifier {
public func modify(widget: UnsafeMutablePointer<GtkWidget>) {
func modify(widget: UnsafeMutablePointer<GtkWidget>) {
gtk_widget_set_halign(widget, alignment.horizontal.gtkValue)
gtk_widget_set_valign(widget, alignment.vertical.gtkValue)
if maxWidth == .infinity {
Expand All @@ -44,13 +42,32 @@ extension _FlexFrameLayout: WidgetModifier {
}
}

extension _BackgroundModifier: WidgetModifier where Background == Color {
public func modify(widget: UnsafeMutablePointer<GtkWidget>) {
let resolved = _ColorProxy(self.background).resolve(in: environment)
var color = GdkRGBA(red: resolved.red,
green: resolved.green,
blue: resolved.blue,
alpha: resolved.opacity)
gtk_widget_override_background_color(widget, GtkStateFlags(rawValue: 0), &color)
}
extension Color {
func cssValue(_ environment: EnvironmentValues) -> String {
let rgba = _ColorProxy(self).resolve(in: environment)
return "rgba(\(rgba.red * 255), \(rgba.green * 255), \(rgba.blue * 255), \(rgba.opacity))"
}
}

// Border modifier
extension _OverlayModifier: WidgetAttributeModifier, WidgetModifier
where Overlay == _ShapeView<_StrokedShape<TokamakCore.Rectangle._Inset>, Color>
{
var attributes: [String: String] {
let style = overlay.shape.style.dashPhase == 0 ? "solid" : "dashed"

return [
"border-style": style,
"border-width": "\(overlay.shape.style.lineWidth)px",
"border-color": overlay.style.cssValue(environment),
"border-radius": "inherit"
]
}
}

extension _BackgroundModifier: WidgetAttributeModifier, WidgetModifier where Background == Color {
var attributes: [String: String] {
let cssValue = background.cssValue(environment)
return ["background": cssValue]
}
}
24 changes: 24 additions & 0 deletions Sources/TokamakGTK/Modifiers/WidgetModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,30 @@ protocol WidgetModifier {
func modify(widget: UnsafeMutablePointer<GtkWidget>)
}

protocol WidgetAttributeModifier: WidgetModifier {
var attributes: [String: String] { get }
}

extension WidgetAttributeModifier {
func modify(widget: UnsafeMutablePointer<GtkWidget>) {
let context = gtk_widget_get_style_context(widget)
let provider = gtk_css_provider_new()

let renderedStyle = attributes.reduce("", { $0 + "\($1.0):\($1.1);"})

gtk_css_provider_load_from_data(provider,
"* { \(renderedStyle) }",
-1,
nil)

gtk_style_context_add_provider(context,
OpaquePointer(provider),
1 /* GTK_STYLE_PROVIDER_PRIORITY_FALLBACK */)

g_object_unref(provider)
}
}

extension ModifiedContent: ViewDeferredToRenderer where Content: View {
public var deferredBody: AnyView {
guard let widgetModifier = modifier as? WidgetModifier else {
Expand Down
4 changes: 3 additions & 1 deletion Sources/TokamakGTKDemo/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ struct Counter: View {
@State private var count: Int = 0
var body: some View {
VStack {
Text("\(count)").background(Color(red: 0.5, green: 1, blue: 0.5))
Text("\(count)")
.background(Color(red: 0.5, green: 1, blue: 0.5))
.border(Color.red, width: 1)
HStack {
Button("Decrement") { count -= 1 }
Button("Increment") { count += 1 }
Expand Down