Closed silenc3r closed 1 year ago
There currently is no simple built-in method for getting a reference to a GTK Widget anywhere in the widget tree. You can however use hooks to get around this limitation. One idea for solving your specific use case might be building something similar to React's refs. Here is a basic implementation of a Ref
widget that extracts the underlying GTK widget of its child.
# License: MIT
# Copyright (c) 2023 Can Joshua Lehmann
import owlkettle/[gtk, widgetutils]
type Cell = ref object
widget*: GtkWidget
proc focus*(cell: Cell) =
gtk_widget_grab_focus(cell.widget)
renderable Ref:
cell: Cell
child: Widget
hooks:
beforeBuild:
state.internalWidget = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0)
hooks child:
(build, update):
proc addChild(box, child: GtkWidget) {.cdecl.} =
gtk_widget_set_hexpand(child, 1)
gtk_box_append(box, child)
state.updateChild(state.child, widget.valChild, addChild, gtk_box_remove)
if not state.cell.isNil:
if state.child.isNil:
state.cell.widget = nil
else:
state.cell.widget = state.child.unwrapInternalWidget()
adder add:
if widget.hasChild:
raise newException(ValueError, "Unable to add multiple children to a Ref.")
widget.hasChild = true
widget.valChild = child
You can then use it like this in the TODO app:
Box(orient = OrientX, spacing = 6) {.expand: false.}:
let entry = Cell()
Ref(cell = entry):
Entry:
text = app.newItem
proc changed(newItem: string) =
app.newItem = newItem
Button {.expand: false.}:
icon = "list-add-symbolic"
style = [ButtonSuggested]
proc clicked() =
app.todos.add(TodoItem(text: app.newItem))
app.newItem = ""
entry.focus()
Hi! In the example TODO app after pressing the + button I want to move focus back to the entry widget. How can I do that? I guess I have to use
gtk_widget_grab_focus
, but how do I get reference to entry widget?