Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

Target a Gtk Cairo context #568

Closed
alhirzel opened this issue Mar 10, 2020 · 19 comments
Closed

Target a Gtk Cairo context #568

alhirzel opened this issue Mar 10, 2020 · 19 comments
Labels
CairoMakie This relates to CairoMakie, the vector backend for Makie based on Cairo. enhancement Feature requests and enhancements planning For discussion and planning development

Comments

@alhirzel
Copy link

(Perhaps I've just missed it)

We should document a way to have CairoMakie paint onto a GtkCanvas from Gtk.jl. Here is an example:

using Gtk, CairoMakie

c = @GtkCanvas()
win = GtkWindow(c, "Easel", 640, 480)

@guarded draw(c) do widget
	ctx = getgc(c)
	surf = cairo_surface(c)
	scene = heatmap(rand(50, 50))

	# ???
end
showall(win)
@SimonDanisch
Copy link
Member

Can you also get the cairo context & surface?

@alhirzel
Copy link
Author

alhirzel commented Mar 10, 2020

@SimonDanisch
Copy link
Member

using Gtk, CairoMakie

c = @GtkCanvas()
win = GtkWindow(c, "Easel", 640, 480)

@guarded draw(c) do widget
    ctx = getgc(c)
    surf = Gtk.cairo_surface(c)
    scene = heatmap(rand(50, 50), resolution=(640, 480))
    screen = CairoMakie.CairoScreen(scene, surf, ctx, nothing)
    CairoMakie.cairo_draw(screen, scene)
end
showall(win)

@alhirzel
Copy link
Author

Cool, I was almost there! This yields:

┌ Warning: Error in @guarded callback
└ @ Main ~/.julia/packages/Gtk/X3A4U/src/base.jl:90
ERROR: MethodError: no method matching getindex(::FreeTypeAbstraction.FTFont, ::Int64)
Stacktrace:
 [1] fontname(::FreeTypeAbstraction.FTFont) at /home/ahirzel/.julia/packages/CairoMakie/3oiBK/src/CairoMakie.jl:397
 [2] (::CairoMakie.var"#17#18"{Scene,Cairo.CairoContext,String,AbstractPlotting.TextureAtlas})(::Int64, ::GeometryTypes.Point{3,Float32}, ::Vec{2,Float32}, ::ColorTypes.RGBA{Float32}, ::FreeTypeAbstraction.FTFont, ::Quaternion{Float32}) at /home/ahirzel/.julia/packages/CairoMakie/3oiBK/src/CairoMakie.jl:479
 [3] broadcast_foreach(::Function, ::UnitRange{Int64}, ::Vararg{Any,N} where N) at /home/ahirzel/.julia/packages/AbstractPlotting/V6N2j/src/utilities/utilities.jl:176
 [4] draw_atomic(::Scene, ::CairoMakie.CairoScreen{Cairo.CairoSurfaceBase{UInt32}}, ::Text{...}) at /home/ahirzel/.julia/packages/CairoMakie/3oiBK/src/CairoMakie.jl:472
 [5] draw_plot(::Scene, ::CairoMakie.CairoScreen{Cairo.CairoSurfaceBase{UInt32}}, ::Text{...}) at /home/ahirzel/.julia/packages/CairoMakie/3oiBK/src/CairoMakie.jl:521
 [6] draw_plot(::Scene, ::CairoMakie.CairoScreen{Cairo.CairoSurfaceBase{UInt32}}, ::Annotations{...}) at /home/ahirzel/.julia/packages/CairoMakie/3oiBK/src/CairoMakie.jl:523 (repeats 2 times)
 [7] draw_plot(::CairoMakie.CairoScreen{Cairo.CairoSurfaceBase{UInt32}}, ::Scene) at /home/ahirzel/.julia/packages/CairoMakie/3oiBK/src/CairoMakie.jl:531
 [8] cairo_draw at /home/ahirzel/.julia/packages/CairoMakie/3oiBK/src/CairoMakie.jl:544 [inlined]
 [9] (::var"#18#19"{GtkCanvas})(::GtkCanvas) at /home/ahirzel/.julia/packages/Gtk/X3A4U/src/base.jl:88
 [10] draw(::GtkCanvas, ::Bool) at /home/ahirzel/.julia/packages/Gtk/X3A4U/src/cairo.jl:86
 [11] notify_resize(::Ptr{GObject}, ::Ptr{Gtk.GdkRectangle}, ::GtkCanvas) at /home/ahirzel/.julia/packages/Gtk/X3A4U/src/cairo.jl:63
 [12] (::Gtk.var"#237#238")() at /home/ahirzel/.julia/packages/Gtk/X3A4U/src/events.jl:2
 [13] g_sigatom(::Any) at /home/ahirzel/.julia/packages/Gtk/X3A4U/src/GLib/signals.jl:176
 [14] gtk_main() at /home/ahirzel/.julia/packages/Gtk/X3A4U/src/events.jl:1

@SimonDanisch
Copy link
Member

I just merged a fix for this! Checkout master and make sure to call ]up;resolve ...

@alhirzel
Copy link
Author

alhirzel commented Mar 10, 2020

Awesome! I wonder if there should be a utility function that passes along resize events to the scene? So that Gtk can manage the canvas size and CairoMakie can respond? Mockup...

drawonto(canvas, scene) = @guarded draw(canvas) do _
	resize!(scene, width(canvas), height(canvas))
	screen = CairoMakie.CairoScreen(scene, Gtk.cairo_surface(canvas), getgc(canvas), nothing)
	CairoMakie.cairo_draw(screen, scene)
end

usage

c = @GtkCanvas()
win = GtkWindow(c, "Easel", 640, 480)
drawonto(c, heatmap(rand(50, 50)))

@asinghvi17
Copy link
Member

You'd need a way to update (a) the Scene's pixel area and (b) the context's pixel area.

(a) is as simple as resize!(scene, size), but I'm not sure about (b).

@asinghvi17
Copy link
Member

I just tried this out, and it works beautifully.

https://developer.gnome.org/gtk-tutorial/stable/x182.html could be useful for seeing which events to track and act on.

@jkrumbiegel jkrumbiegel transferred this issue from JuliaPlots/CairoMakie.jl Apr 27, 2020
@jkrumbiegel jkrumbiegel added CairoMakie This relates to CairoMakie, the vector backend for Makie based on Cairo. enhancement Feature requests and enhancements labels Apr 27, 2020
@sharpTrick
Copy link

I messed around with this a little. The following appears to be a good way to get the context's dynamic pixel area.

using Gtk, Makie, CairoMakie

c = @GtkCanvas()
win = GtkWindow(c, "Easel", 640, 480)

@guarded draw(c) do widget
    ctx = getgc(c)
    surf = Gtk.cairo_surface(c)
    scene = heatmap(rand(50, 50), resolution=(surf.width, surf.height))
    screen = CairoMakie.CairoScreen(scene, surf, ctx, nothing)
    CairoMakie.cairo_draw(screen, scene)
end

showall(win)

Obviously one would create the scene outside of draw(c) and simply call resize!(scene, size) inside the draw function.

@filchristou
Copy link

filchristou commented Nov 4, 2021

I 've been searching for this! Do you think that this can at some point land in the CairoMakie.jl , so you can directly illustrate static figures with such GtkWindows? Currently in REPL you must save in a specific format and open outside the julia kernel to see the figure.
It would be great to have a simple showGtk(CairoFigure) function that immeadiately pops up the figure !

@feanor12
Copy link

feanor12 commented Nov 1, 2022

I had a go at this and I came up with a small example.
Maybe, if I have time, I'll try to make a GtkMakieCanvas.jl or something similar.

using Gtk, Makie, CairoMakie

function createMakieCanvas(figure)
  c = @GtkCanvas()
  @guarded draw(c) do widget
    surf = Gtk.cairo_surface(c)
    scene = figure.scene
    resize!(scene, (surf.width,surf.height))
    config = CairoMakie.ScreenConfig(1.0,1.0,:good,true,true)
    screen = CairoMakie.Screen(scene, surf, config)
    CairoMakie.cairo_draw(screen, scene)
  end
  return c
end

win = GtkWindow("demo", 640, 480)
box = GtkBox(:v)
push!(win,box)
button = GtkButton("plot")
push!(box,button)
f = Figure()
ax = Axis(f[1,1])
c = createMakieCanvas(f)
push!(box,c)
set_gtk_property!(box,:expand,c,true)

function on_plot(w)
    empty!(ax)
    heatmap!(ax,rand(100,20))
    draw(c)
end
signal_connect(on_plot, button, "clicked")

showall(win)
while true
    sleep(1)
end

@tknopp
Copy link
Contributor

tknopp commented Dec 24, 2022

@jkrumbiegel @SimonDanisch: Is there any reason why CairoMakie does not ship with Gtk Window integration for the REPL like for instance Winston.jl does it? The inconvenience to get a quick plot is right now the only reason to prefer other plotting tools for me at the moment.

@jkrumbiegel
Copy link
Member

We could think about adding that as a weak dependency. So for people with GTK installed, that would give an additional way of showing cairomakie plots.

@tknopp
Copy link
Contributor

tknopp commented Dec 24, 2022

What do you mean by weak dependency? JuliaLang/julia#47695? I have not looked at it yet but if that is the proposal I think this would be great. Just „using Gtk, CairoMakie“ and then have plots showing up.

@jkrumbiegel
Copy link
Member

Yes exactly, a bit like Requires but with first class support and precompilation.

@tknopp
Copy link
Contributor

tknopp commented Dec 30, 2022

I just tried this example:
https://github.com/MakieOrg/Makie.jl/blob/master/CairoMakie/README.md#using-cairomakie-with-gtkjl
which seem to be broken:

┌ Warning: Error in @guarded callback
│   exception =
│    MethodError: no method matching CairoMakie.Screen(::Scene, ::Cairo.CairoSurfaceBase{UInt32}, ::Cairo.CairoContext, ::Nothing)
│    Closest candidates are:
│      CairoMakie.Screen(::Scene; screen_config...) at ~/.julia/packages/CairoMakie/ihglX/src/screen.jl:239
│      CairoMakie.Screen(::Scene, ::CairoMakie.ScreenConfig) at ~/.julia/packages/CairoMakie/ihglX/src/screen.jl:244
│      CairoMakie.Screen(::Scene, ::CairoMakie.ScreenConfig, ::Cairo.CairoSurface) at ~/.julia/packages/CairoMakie/ihglX/src/screen.jl:270...
│    Stacktrace:
│     [1] macro expansion
│       @ ./REPL[4]:5 [inlined]
│     [2] (::var"#1#2"{GtkCanvas, Figure})(#unused#::GtkCanvas)
│       @ Main ~/.julia/dev/Gtk/src/base.jl:112
│     [3] draw(widget::GtkCanvas, immediate::Bool)
│       @ Gtk ~/.julia/dev/Gtk/src/cairo.jl:86
│     [4] notify_resize(#unused#::Ptr{GObject}, size::Ptr{Gtk.GdkRectangle}, widget::GtkCanvas)
│       @ Gtk ~/.julia/dev/Gtk/src/cairo.jl:63
│     [5] (::Gtk.var"#253#254")()
│       @ Gtk ~/.julia/dev/Gtk/src/events.jl:2
│     [6] g_sigatom(f::Any)
│       @ Gtk.GLib ~/.julia/dev/Gtk/src/GLib/signals.jl:176
│     [7] gtk_main()
│       @ Gtk ~/.julia/dev/Gtk/src/events.jl:1
└ @ Main ~/.julia/dev/Gtk/src/base.jl:114

@00krishna
Copy link

00krishna commented Jan 6, 2023

I can confirm that I am encountering the same error message as @tknopp when running the GTK and Makie code from the README. My stacktrace is the same as Tknopp's as well. I am running Julia 1.8.3 on Ubuntu 20.04, and I also get a popup application window that is completely blank--no controls visible.

@feanor12
Copy link

feanor12 commented Jan 7, 2023

By replacing drawonto with

function drawonto(canvas, figure)
  @guarded draw(canvas) do _
    scene = figure.scene
    resize!(scene, Gtk.width(canvas), Gtk.height(canvas))
    config = CairoMakie.ScreenConfig(1.0,1.0,:good,true,true)
    screen = CairoMakie.Screen(scene, config, Gtk.cairo_surface(canvas))
    CairoMakie.cairo_draw(screen, scene)
  end
end

I got a working example.

@tknopp
Copy link
Contributor

tknopp commented Jan 7, 2023

See #2537

@ffreyer ffreyer added the planning For discussion and planning development label Aug 21, 2024
@MakieOrg MakieOrg locked and limited conversation to collaborators Aug 22, 2024
@ffreyer ffreyer converted this issue into discussion #4181 Aug 22, 2024

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
CairoMakie This relates to CairoMakie, the vector backend for Makie based on Cairo. enhancement Feature requests and enhancements planning For discussion and planning development
Projects
None yet
Development

No branches or pull requests

10 participants