Features/GTK3/Porting/Typing Turtle
This page is being performed while I'm porting Typing Turtle Activity to Gtk3.
There is a ticket with some useful information that I'm using on the porting and to keep tracking this port. Besides, this wiki page will be useful to write some code snippets about what are the difficulties that I'm having on the port and maybe can be useful for someone else.
I will take this guide as reference on the Gtk3 porting.
Port to Cairo
README: before to port this activity to GTK3, we should port it to Cairo as the first step and then move to GTK3.
Code Snippets
Draw a rectangle
To draw a rectangle we used to do:
gc = self.window.new_gc() gc.foreground = self.area.get_colormap().alloc_color(50000, 50000, 50000) self.area.window.draw_rectangle(gc, True, x, y, w, h)
The arguments for alloc_color are between 0-65535 and the set_source_rgb method from cairo are between 0-1, so we have to convert these values as well:
cr.set_source_rgb(0.762, 0.762, 0.762) cr.rectangle(x, y, w, h) cr.fill()
Note that the second attributo of draw_rectangle tells us about if the rectangle is filled or not. In this case is True, so we use cr.fill() in the new way but if we want just the outside lines of the rectangle we should use cr.stroke()
Write some text
This is the old way to do it:
title = _('You finished!') layout = self.area.create_pango_layout(title) layout.set_font_description(pango.FontDescription('Serif Bold 16')) size = layout.get_size() tx = x+w/2-(size[0]/pango.SCALE)/2 ty = y + 100 self.area.window.draw_layout(gc, tx, ty, layout)
and this is the way that I used to do it with pangocairo:
title = _('You finished!') pango_cr = pangocairo.CairoContext(cr) pango_cr.set_source_rgb(0, 0, 0) pango_layout = cr.create_layout() pango_layout.set_font_description(pango.FontDescription('Serif Bold 16')) pango_layout.set_text(title) size = pango_layout.get_size() tx = x + (w / 2) - (size[0] / pango.SCALE) / 2 ty = y + 100 pango_cr.move_to(tx, ty) pango_cr.show_layout(pango_layout) pango_cr.stroke()
Draw a line
This is the old way:
gc.foreground = self.area.get_colormap().alloc_color(0, 0, 0) self.area.window.draw_line(gc, int(b.x), int(b.y + b.size / 2), int(b.x), int(b.y + b.size))
and should be replaced by this new way using cairo
cr.set_source_rgb(0, 0, 0) cr.move_to(int(b.x), int(b.y + b.size / 2)) cr.line_to(int(b.x), int(b.y + b.size)) cr.stroke()
Draw an arc
Old way to do it (notice the second argument of draw_arc: filled):
gc.foreground = self.area.get_colormap().alloc_color(b.color[0],b.color[1],b.color[2]) self.area.window.draw_arc(gc, True, x-b.size/2, y-b.size/2, b.size, b.size, 0, 360*64)
new way:
cr.set_source_rgb(b.color[0], b.color[1], b.color[2]) cr.arc(b.x, b.y, b.size / 2, 0, 2 * math.pi) cr.fill()
Tips & tricks
Convert cairo.Surface to GdkPixbuf
import StringIO
surface = cairo.ImageSurface(cairo.FORMAT_RGB24, w, h) cr = cairo.Context(surface)
[... draw something into the surface ...]
pixbuf_data = StringIO.StringIO() surface.write_to_png(pixbuf_data) pxb_loader = gtk.gdk.PixbufLoader(image_type='png') pxb_loader.write(pixbuf_data.getvalue()) temp_pix = pxb_loader.get_pixbuf() pxb_loader.close()
Paint a GdkPixbuf into the canvas
cr.set_source_pixbuf(self.backgroundpixbuf, 0, 0) cr.rectangle(x, 0, self.backgroundpixbuf.get_width(), self.backgroundpixbuf.get_height()) cr.paint()
Code Snippets
Gtk.TextBuffer
self.lessonbuffer = gtk.TextBuffer(self.tagtable) self.lessontext = gtk.TextView(self.lessonbuffer)
replaced by:
self.lessonbuffer = Gtk.TextBuffer.new(self.tagtable) self.lessontext = Gtk.TextView.new_with_buffer(self.lessonbuffer)
Gdk.Event
event.state
replaced by:
event.get_state()
Rsvg
import rsvg image = rsvg.Handle(file=filename)
replaced by:
from gi.repository import Rsvg image = Rsvg.Handle.new_from_file(filename)
Gtk.TextTag
instructions_tag = Gtk.TextTag('instructions')
replaced by:
instructions_tag = Gtk.TextTag.new('instructions')
Gdk.Keymap
entries = self.keymap.get_entries_for_keyval(keyval) for e in entries: e[0], e[1], e[2]
replaced by:
valid, entries = self.keymap.get_entries_for_keyval(keyval) for e in entries: e.keycode, e.group, e.level
Every entry was a tuple of (keycode, group, level). Now, this is an object with those attributes.
Notes
- I found this chunk of code in the source (keyboard.py L515) and I didn't understand what it means
# Hack to get the current modifier state - which will not be represented by the event. state = gtk.gdk.device_get_core_pointer().get_state(self.window)[1]