Changing Gtk widget border/background colors

I’m having a bit of difficulty trying to understand how one would set the background or border color of a widget with Gtk.jl. I’ve taken a look at this issue, but haven’t been able to make it work with Julia 0.6 and Gtk master (the color doesn’t change). Here’s my snippet:

using Gtk, Gtk.ShortNames

win = Window("Test")
lbl = Label("Some text")
push!(win, lbl)
showall(win)

sc = Gtk.GAccessor.style_context(lbl)
pr = CssProviderLeaf(data="GtkLabel {color:blue}")
push!(sc, StyleProvider(pr), 600)

sleep(5)

I’ve also attempted to read the Gtk documentation to find some semblance of an answer, but haven’t found it terribly helpful in relation to Gtk.jl. I’ve seen methods like G_.background_color, but it seems like this just retrieves the current background color of the supplied StyleContext.

I also noticed that there is a signal called “draw” that is apparently fired when a widget is supposed to draw itself. It’s supposed to provide both the GtkWidget being drawn, and the cairo_t struct (which I assume can be converted to a CairoContext somehow) to the supplied callback. However, the following snippet of code shows that cr is some sort of object like Gtk.GLib.GBoxedUnkown(Ptr{Gtk.GLib.GBoxed} @0x0000000002c6d310), which I’m not sure how to handle.

using Gtk, Gtk.ShortNames, Cairo

win = Window("Test")
lbl = Label("Some text")
push!(win, lbl)

signal_connect(lbl, "draw") do widget, cr
  @async info(widget)
  @async info(cr)
  nothing
end
showall(win)

sleep(5)

What I’m looking for is either some way to use the StyleContext for coloring and styling, or alternatively some way to access the underlying CairoContext of a widget, so that I can manually draw in the colors (or even a gradient or image). Could someone more experienced with Gtk.jl shed some light on what I’m missing? Thanks!

1 Like

So, through a bunch of head-banging and searching of documentation, I managed to partially answer my question, using the second option (getting and drawing to the underlying CairoContext). Here’s what I’ve got:

using Gtk, Gtk.ShortNames, Cairo

win = Window("Test")
lbl = Label("Some text")
push!(win, lbl)

signal_connect(lbl, "draw") do widget, cr
  w, h = width(widget), height(widget)
  @async info(cr)
  ctxptr = convert(Ptr{Void}, cr.handle)
  ctx = CairoContext(ctxptr)
  set_source_rgb(ctx, 0.5, 0, 0.5)
  rectangle(ctx, 0, 0, w, h)
  fill(ctx)
  nothing
end
showall(win)

sleep(5)

This sets the label’s background to a pleasing purple color. The question I now have, is whether this can be used to color in only the border of a widget, while leaving the drawing of the internal area to the widget? If it helps to understand why I want this, I want to use this as a sort of “highlighting” for a keyboard-driven Gtk program which has a hierarchy of nested Gtk widgets. Because I want to be able to indicate to the user which widget in the hierarchy they’re focused on (a box, a label, a canvas, etc.) I was planning to color the border for the “focused” widget with a color to indicate that the widget is in focus. Therefore, while coloring the entire background of a widget is nice, it’s not exactly what I’m looking for: I need to only color the border area. Is there a way to do this that is possibly similar to my above snippet?

EDIT: I really should take more time to try things before I post! I figured out a way to do what I’m looking for using the same concept as above, and am posting it in case anyone else has a need for something similar:

sing Gtk, Gtk.ShortNames, Cairo

win = Window("Test")
box = Box(:h)
push!(win, box)
lbl1 = Label("Some text")
push!(box, lbl1)
setproperty!(lbl1, "margin", 10)
setproperty!(lbl1, "expand", true)
lbl2 = Label("Some text")
push!(box, lbl2)
setproperty!(lbl2, "margin", 10)
setproperty!(lbl2, "expand", true)

signal_connect(box, "draw") do widget, cr
  w, h = width(widget), height(widget)
  @async info(w, " ", h)
  @async info(cr)
  ctxptr = convert(Ptr{Void}, cr.handle)
  ctx = CairoContext(ctxptr)
  set_source_rgb(ctx, 0.5, 0, 0.5)
  rectangle(ctx, 0, 0, w, h)
  fill(ctx)
  nothing
end
signal_connect(lbl1, "draw") do widget, cr
  w, h = width(widget), height(widget)
  @async info(w, " ", h)
  @async info(cr)
  ctxptr = convert(Ptr{Void}, cr.handle)
  ctx = CairoContext(ctxptr)
  set_source_rgb(ctx, 0, 0, 0)
  rectangle(ctx, 0, 0, w, h)
  fill(ctx)
  nothing
end
signal_connect(lbl2, "draw") do widget, cr
  w, h = width(widget), height(widget)
  @async info(w, " ", h)
  @async info(cr)
  ctxptr = convert(Ptr{Void}, cr.handle)
  ctx = CairoContext(ctxptr)
  set_source_rgb(ctx, 0, 0, 0)
  rectangle(ctx, 0, 0, w, h)
  fill(ctx)
  nothing
end
showall(win)

sleep(5)

This:

pr = CssProviderLeaf(data="* {color:blue;}")

or this

pr = CssProviderLeaf(data="label {color:blue;}")

works. I don’t really know why though. Someone should figure out this and maybe redesign/write a good doc for that part of Gtk.jl. CssProviderLeaf also calls repetitively gtk_css_provider_get_default which gives you the Duplicate Julia object creation detected for GObject warnings.

1 Like
GAccessor.markup(widget, "<span background=\"green\">" * label * "</span>")