diff --git a/docs/guide.md b/docs/guide.md index af960f53..0b697528 100644 --- a/docs/guide.md +++ b/docs/guide.md @@ -1,9 +1,11 @@ -# lgi User's Guide + # lgi User's Guide All lgi functionality is exported through `lgi` module. To access it, use standard `require` construct, e.g.: - local lgi = require 'lgi' +```lua +local lgi = require 'lgi' +``` Note that lgi does not use `module` function, so it does *not* automatically insert itself into globals, the return value from @@ -15,15 +17,19 @@ To use any introspection-enabled library, it has to be imported first. Simple way to import it is just referencing its name in `lgi` namespace, like this: - local GLib = lgi.GLib - local GObject = lgi.GObject - local Gtk = lgi.Gtk +```lua +local GLib = lgi.GLib +local GObject = lgi.GObject +local Gtk = lgi.Gtk +``` This imports the latest version of the module which can be found. When exact version is requested, use `lgi.require(modulename, version)`: - local Gst = lgi.require('Gst', '0.10') +```lua +local Gst = lgi.require('Gst', '0.10') +``` ### 1.1. Repository structure @@ -31,7 +37,9 @@ Importing library creates table containing all elements which are present in the library namespace - all classes, structures, global functions, constants etc. All those elements are directly accessible, e.g. - assert(GLib.PRIORITY_DEFAULT == 0) +```lua +assert(GLib.PRIORITY_DEFAULT == 0) +``` Note that all elements in the namespace are lazy-loaded to avoid excessive memory overhead and initial loading time. To force @@ -40,11 +48,15 @@ classes, structures, enums etc) contains `_resolve(deep)` method, which loads all contents eagerly, possibly recursively if `deep` argument is `true`. So e.g. - dump(Gtk.Widget:_resolve(true), 3) +```lua +dump(Gtk.Widget:_resolve(true), 3) +``` prints everything available in Gtk.Widget class, and - dump(Gio:_resolve(true), 5) +```lua +dump(Gio:_resolve(true), 5) +``` dumps the whole contents of Gio package. @@ -83,9 +95,9 @@ mapping between GLib types and Lua types is established. `NULL`). * `gpointer` are mapped to Lua `lightuserdata` type. In Lua->GLib direction, following values are accepted for `gpointer` type: - - Lua `string` instances - - Instances of lgi classes, structs or unions - - Binary buffers (see below) +- Lua `string` instances +- Instances of lgi classes, structs or unions +- Binary buffers (see below) ### 2.1. Calling functions and methods @@ -110,17 +122,21 @@ GtkTreeIter *iter)`, where `iter` is filled in case of success, and untouched in case of failure. Normal binding of such function feels a bit unnatural in Lua: - local ok, iter = model:get_iter_first() - -- Even in case of failure, iter contains new 0-initialized - -- instance of the iterator, so following line is necessary: - if not ok then iter = nil end +```lua +local ok, iter = model:get_iter_first() +-- Even in case of failure, iter contains new 0-initialized +-- instance of the iterator, so following line is necessary: +if not ok then iter = nil end +``` To ease usage of such method, lgi avoids returning first boolean return. If C function returns `false` in this case, all other output arguments are returned as `nil`. This means that previous example must be instead written simply as: - local iter = model:get_iter_first() +```lua +local iter = model:get_iter_first() +``` ### 2.2. Callbacks @@ -172,17 +188,21 @@ workaround for possible bug in lgi :-) To create new instance of the class (i.e. new object), call class declaration as if it is a method: - local window = Gtk.Window() +```lua +local window = Gtk.Window() +``` Optionally, it is possible to pass single argument, table containing entity name mapping to entity value. This way it is possible to initialize properties, fields and even signal handlers in the class construction: - local window = Gtk.Window { - title = "Title", - on_destroy = function() print("Destroyed") end - } +```lua +local window = Gtk.Window { + title = "Title", + on_destroy = function() print("Destroyed") end +} +``` For some classes, which behave like containers of other things, lgi allows adding also a list of children into the array part of the @@ -191,22 +211,26 @@ typical example is `Gtk.Container`, which allows adding element in the constructor table, allowing construction of the whole widget hierarchy in Lua-friendly way: - local window = Gtk.Window { - title = "Title", - on_destroy = function() print("Destroyed") end, - Gtk.Grid { - Gtk.Label { label = "Contents", expand = true }, - Gtk.Statusbar {} - } - } +```lua +local window = Gtk.Window { + title = "Title", + on_destroy = function() print("Destroyed") end, + Gtk.Grid { + Gtk.Label { label = "Contents", expand = true }, + Gtk.Statusbar {} + } +} +``` There is also possibility to create instances of classes for which the introspection typelib data is not available, only GType is known. Use `GObject.Object.new()` as illustrated in following sample: - local gtype = 'ForeignWidget' - local widget = GObject.Object.new(gtype) - local window = Gtk.Window { title = 'foreign', widget } +```lua +local gtype = 'ForeignWidget' +local widget = GObject.Object.new(gtype) +local window = Gtk.Window { title = 'foreign', widget } +``` ### 3.2. Calling methods @@ -258,33 +282,39 @@ Assigning Lua function connects that function to the signal. Signal routine gets object as first argument, followed by other arguments of the signal. Simple example: - local window = Gtk.Window() - window.on_destroy = function(w) - assert(w == window) - print("Destroyed", w) - end +```lua +local window = Gtk.Window() +window.on_destroy = function(w) + assert(w == window) + print("Destroyed", w) +end +``` Note that because of Lua's syntactic sugar for object access and function definition, it is possible to use signal connection even in following way: - local window = Gtk.Window() - function window:on_destroy() - assert(self == window) - print("Destroyed", self) - end +```lua +local window = Gtk.Window() +function window:on_destroy() + assert(self == window) + print("Destroyed", self) +end +``` Reading signal entity provides temporary table which can be used for connecting signal with specification of the signal detail (see GObject documentation on signal detail explanation). An example of handler which is notified whenever window is activated or deactivated follows: - local window = Gtk.Window() - window.on_notify['is-active'] = function(self, pspec) - assert(self == window) - assert(pspec.name == 'is-active') - print("Window is active:", self.is_active) - end +```lua +local window = Gtk.Window() +window.on_notify['is-active'] = function(self, pspec) + assert(self == window) + assert(pspec.name == 'is-active') + print("Window is active:", self.is_active) +end +``` Both forms of signal connection connect handler before default signal handler. If connection after default signal handler is wanted (see @@ -293,13 +323,15 @@ connection call has to be used: `object.on_signalname:connect(target, detail, after)`. Previous example rewritten using this connection style follows: - local window = Gtk.Window() - local function notify_handler(self, pspec) - assert(self == window) - assert(pspec.name == 'is-active') - print("Window is active:", self.is_active) - end - window.on_notify:connect(notify_handler, 'is-active', false) +```lua +local window = Gtk.Window() +local function notify_handler(self, pspec) + assert(self == window) + assert(pspec.name == 'is-active') + print("Window is active:", self.is_active) +end +window.on_notify:connect(notify_handler, 'is-active', false) +``` #### 3.4.2 Emitting signals @@ -307,8 +339,10 @@ Emitting existing signals is usually needed only when implementing subclasses of existing classes. Simplest method to emit a signal is to 'call' the signal on the class instance: - local treemodel = - treemodel:on_row_inserted(path, iter) +```lua +local treemodel = +treemodel:on_row_inserted(path, iter) +``` ### 3.5. Dynamic typing of classes @@ -324,14 +358,16 @@ Hopefully everything can be explained in following example. Assume that `demo.ui` is GtkBuilder file containing definition of `GtkWindow` labeled `window1` and `GtkAction` called `action1` (among others). - local builder = Gtk.Builder() - builder:add_from_file('demo.ui') - local window = builder:get_object('window1') - -- Call Gtk.Window-specific method - window:iconify() - local action = builder:get_object('action1') - -- Set Gtk.Action-specific property - action.sensitive = false +```lua +local builder = Gtk.Builder() +builder:add_from_file('demo.ui') +local window = builder:get_object('window1') +-- Call Gtk.Window-specific method +window:iconify() +local action = builder:get_object('action1') +-- Set Gtk.Action-specific property +action.sensitive = false +``` Although `Gtk.Builder.get_object()` method is marked as returning `GObject*`, lgi actually checks the real type of returned object and @@ -353,23 +389,27 @@ properties registered for object's class, GObject library provides `g_object_class_list_properties()` function. Following sample lists all properties registered for the given object instance. - function dump_props(obj) - print("Dumping properties of ", obj) - for _, pspec in pairs(obj._class:list_properties()) do - print(pspec.name, pspec.value_type) - end - end +```lua +function dump_props(obj) + print("Dumping properties of ", obj) + for _, pspec in pairs(obj._class:list_properties()) do + print(pspec.name, pspec.value_type) + end +end +``` Running `dump_props(Gtk.Window())` yields following output: - Dumping props of lgi.obj 0xe5c070:Gtk.Window(GtkWindow) - name gchararray - parent GtkContainer - width-request gint - height-request gint - visible gboolean - sensitive gboolean - ... (and so on) +```lua +Dumping props of lgi.obj 0xe5c070:Gtk.Window(GtkWindow) +name gchararray +parent GtkContainer +width-request gint +height-request gint +visible gboolean +sensitive gboolean +... (and so on) +``` ### 3.7. Querying the type of the object instances @@ -380,23 +420,27 @@ instance of specified class (or implements specified interface, when called on interface instances). Following examples demonstrate usage of this construct: - local window = Gtk.Window() - print(Gtk.Window:is_type_of(window)) -- prints 'true' - print(Gtk.Widget:is_type_of(window)) -- prints 'true' - print(Gtk.Buildable:is_type_of(window)) -- prints 'true' - print(Gtk.Action:is_type_of(window)) -- prints 'false' - print(Gtk.Window:is_type_of('string')) -- prints 'false' - print(Gtk.Window:is_type_of(nil)) -- prints 'false' +```lua +local window = Gtk.Window() +print(Gtk.Window:is_type_of(window)) -- prints 'true' +print(Gtk.Widget:is_type_of(window)) -- prints 'true' +print(Gtk.Buildable:is_type_of(window)) -- prints 'true' +print(Gtk.Action:is_type_of(window)) -- prints 'false' +print(Gtk.Window:is_type_of('string')) -- prints 'false' +print(Gtk.Window:is_type_of(nil)) -- prints 'false' +``` There is also possibility to query the type-table from instantiated object, using `_type` property. - -- Checks, whether 'unknown' conforms to the type of the 'template' - -- object. - function same_type(template, unknown) - local type = template._type - return type:is_type_of(unknown) - end +```lua +-- Checks, whether 'unknown' conforms to the type of the 'template' +-- object. +function same_type(template, unknown) + local type = template._type + return type:is_type_of(unknown) +end +``` ### 3.8. Implementing subclasses @@ -408,26 +452,34 @@ In order to create subclass, lgi requires to create `package` first, which is basically namespace where the new classes will live. To create a package, use `lgi.package` function: - -- Create MyApp package - local MyApp = lgi.package 'MyApp' +```lua +-- Create MyApp package +local MyApp = lgi.package 'MyApp' +``` Once the package is created, it is possible to reference it from `lgi` as any other existing namespace: - local Gtk = lgi.Gtk - local MyApp = lgi.MyApp +```lua +local Gtk = lgi.Gtk +local MyApp = lgi.MyApp +``` To create subclass, use package's method `class(name, parent[, ifacelist])`: - MyApp:class('MyWidget', Gtk.Widget) - MyApp:class('MyModel', GObject.Object, { Gtk.TreeModel }) +```lua +MyApp:class('MyWidget', Gtk.Widget) +MyApp:class('MyModel', GObject.Object, { Gtk.TreeModel }) +``` After that, newly created class behaves exactly the same as classes picked up from GObjectIntrospection namespaces, like shown in following examples: - local widget = MyApp.MyWidget() - widget:show() +```lua +local widget = MyApp.MyWidget() +widget:show() +``` Note that it is important to override virtual methods _before_ any instance of the derived class (see chapter about virtual methods @@ -443,21 +495,25 @@ which is plain Lua table and allows subclass implementation to store some internal status. All these techniques are illustrated in following sample: - function MyApp.MyWidget:do_show() - if not self.priv.invisible then - -- All three lines perform forwarding to inherited virtual: - Gtk.Widget.do_show(self) - -- or: - MyApp.MyWidget._parent.do_show(self) - -- or: - self._type._parent.do_show(self) - end - end - - -- Convenience method for setting MyWidget 'invisible' - function MyApp.MyWidget:set_invisible(invisible) - self.priv.invisible = invisible - end +```lua +function MyApp.MyWidget:do_show() + if not self.priv.invisible then + -- All three lines perform forwarding to inherited virtual: + Gtk.Widget.do_show(self) + -- or: + MyApp.MyWidget._parent.do_show(self) + -- or: + self._type._parent.do_show(self) + end +end +``` + +```lua +-- Convenience method for setting MyWidget 'invisible' +function MyApp.MyWidget:set_invisible(invisible) + self.priv.invisible = invisible +end +``` The important fact is that virtual method overrides are picked up only up to the first instantiation of the class or inheriting new subclass @@ -475,22 +531,28 @@ setter method in `_property_set` and `_property_get` tables. Both approaches are illustrated in the following example with property called `my_label` - MyApp.MyWidget._property.my_label = GObject.ParamSpecString( - 'my_label', 'Nick string', 'Blurb string', 'def-value', - { 'READABLE', 'WRITABLE', 'CONSTRUCT' }) - function MyApp.MyWidget._property_set:my_label(new_value) - print(('%s changed my_label from %s to %s'):format( - self, self.priv-my_label, new_value)) - self.priv.my_label = new_value - end - local widget = MyApp.MyWidget() - - -- Access through GObject's property machinery - widget.my_label = 'label1' - print(widget.my_label) - - -- Direct access to underlying storage - print(widget.priv.my_label) +```lua +MyApp.MyWidget._property.my_label = GObject.ParamSpecString( + 'my_label', 'Nick string', 'Blurb string', 'def-value', + { 'READABLE', 'WRITABLE', 'CONSTRUCT' }) +function MyApp.MyWidget._property_set:my_label(new_value) + print(('%s changed my_label from %s to %s'):format( + self, self.priv-my_label, new_value)) + self.priv.my_label = new_value +end +local widget = MyApp.MyWidget() +``` + +```lua +-- Access through GObject's property machinery +widget.my_label = 'label1' +print(widget.my_label) +``` + +```lua +-- Direct access to underlying storage +print(widget.priv.my_label) +``` ## 4. Structures and unions @@ -520,17 +582,21 @@ equivalent with `local main_loop = GLib.MainLoop.new(nil, false)`, and Structure methods are called in the same way as class methods: `struct:method()`, or `StructType.method()`. For example: - local loop = GLib.MainLoop(nil, false) - loop:run() - -- Following line is equivalent - GLib.MainLoop.run(loop) +```lua +local loop = GLib.MainLoop(nil, false) +loop:run() +-- Following line is equivalent +GLib.MainLoop.run(loop) +``` Fields are accessed using `.` operator on structure instance, for example - local color = Gdk.RGBA { alpha = 1 } - color.green = 0.5 - print(color.red, color.green, color.alpha) - -- Prints: 0 0.5 1 +```lua +local color = Gdk.RGBA { alpha = 1 } +color.green = 0.5 +print(color.red, color.green, color.alpha) +-- Prints: 0 0.5 1 +``` ## 5. Enums and bitflags, constants @@ -558,10 +624,12 @@ yields following output: > dump(Gtk.WindowType) - ["table: 0xef9bc0"] = { -- table: 0xef9bc0 - TOPLEVEL = 0; - POPUP = 1; - }; +```lua +["table: 0xef9bc0"] = { -- table: 0xef9bc0 + TOPLEVEL = 0; + POPUP = 1; +}; +``` so constants can be referenced using `Gtk.WindowType.TOPLEVEL` construct, or directly using string `'TOPLEVEL'` when a @@ -575,49 +643,61 @@ actually provides symbolic name to which the specified constant maps: > print(Gtk.WindowType[0]) - TOPLEVEL +```lua +TOPLEVEL +``` > print(Gtk.WindowType[2]) - nil +```lua +nil +``` Indexing bitflags table with number provides table containing list of all symbolic names which make up the requested value: > dump(Gtk.RegionFlags) - ["table: 0xe5dd10"] = { -- table: 0xe5dd10 - ODD = 2; - EVEN = 1; - SORTED = 32; - FIRST = 4; - LAST = 8; +```lua +["table: 0xe5dd10"] = { -- table: 0xe5dd10 + ODD = 2; + EVEN = 1; + SORTED = 32; + FIRST = 4; + LAST = 8; +``` > dump(Gtk.RegionFlags[34]) - ["table: 0xedbba0"] = { -- table: 0xedbba0 - SORTED = 32; - ODD = 2; - }; +```lua +["table: 0xedbba0"] = { -- table: 0xedbba0 + SORTED = 32; + ODD = 2; +}; +``` This way, it is possible to check for presence of specified flag very easily: - if Gtk.RegionFlags[flags].ODD then - -- Code handling region-odd case - endif +```lua +if Gtk.RegionFlags[flags].ODD then + -- Code handling region-odd case +endif +``` If the value cannot be cleanly decomposed to known flags, remaining bits are accumulated into number stored at index 1: > dump(Gtk.RegionFlags[51]) - ["table: 0x242fb20"] = { -- table: 0x242fb20 - EVEN = 1; - SORTED = 32; - [1] = 16; - ODD = 2; - }; +```lua +["table: 0x242fb20"] = { -- table: 0x242fb20 + EVEN = 1; + SORTED = 32; + [1] = 16; + ODD = 2; +}; +``` To construct numeric value which can be passed to a function expecting an enum, it is possible to simply add requested flags. However, there @@ -628,11 +708,15 @@ requested flags: > =Gtk.RegionFlags { 'FIRST', 'SORTED' } - 36 +```lua +36 +``` > =Gtk.RegionFlags { Gtk.RegionFlags.ODD, 16, 'EVEN' } - 19 +```lua +19 +``` ## 6. Threading and synchronization @@ -678,14 +762,20 @@ returns table containing methods `message`, `warning`, `critical`, followed by inserts and logs specified string. An example of typical usage follows: - local lgi = require 'lgi' - local log = lgi.log.domain('myapp') +```lua +local lgi = require 'lgi' +local log = lgi.log.domain('myapp') +``` - -- This is equivalent of C 'g_message("A message %d", 1)' - log.message("A message %d", 1) +```lua +-- This is equivalent of C 'g_message("A message %d", 1)' +log.message("A message %d", 1) +``` - -- This is equivalent to C 'g_warning("Not found")' - log.warning("Not found") +```lua +-- This is equivalent to C 'g_warning("Not found")' +log.warning("Not found") +``` Note that format string is formatted using Lua's `string.format()`, so the rules for Lua formatting strings apply here. @@ -700,27 +790,29 @@ create lgi object from external pointer, it is possible to pass lightuserdata with object pointer to type constructor. Following example illustrates both techniques: - -- Create Lua-side window object. - local window = Gtk.Window { title = 'Hello' } - - -- Get native pointer to this object. - local window_ptr = window._native - - // window_ptr can be now passed to C code, which can use it. - GtkWindow *window = lua_touserdata (L, x); - char *title; - g_object_get (window, "title", &title); - g_assert (g_str_equal (title, "Hello")); - g_free (title); - - // Create object on the C side and pass it to Lua - GtkButton *button = gtk_button_new_with_label ("Foreign"); - lua_pushlightuserdata (L, button); - lua_call (L, ...); - - -- Retrieve button on the Lua side. - assert(type(button) == 'userdata') - window:add(Gtk.Button(button)) +```lua +-- Create Lua-side window object. +local window = Gtk.Window { title = 'Hello' } + +-- Get native pointer to this object. +local window_ptr = window._native + +// window_ptr can be now passed to C code, which can use it. +GtkWindow *window = lua_touserdata (L, x); +char *title; +g_object_get (window, "title", &title); +g_assert (g_str_equal (title, "Hello")); +g_free (title); + +// Create object on the C side and pass it to Lua +GtkButton *button = gtk_button_new_with_label ("Foreign"); +lua_pushlightuserdata (L, button); +lua_call (L, ...); + +-- Retrieve button on the Lua side. +assert(type(button) == 'userdata') +window:add(Gtk.Button(button)) +``` Note that while the example demonstrates objects, the same mechanism works also for structures and unions. @@ -757,8 +849,10 @@ Moreover, functions operating on `GType` are also present in There is special new method, `Type.type(gtype)` which returns lgi native type representing specified gtype. For example: - assert(Gtk.Window == GObject.Type.type('GtkWindow')) - assert(Gtk.WidgetPath == GObject.Type.type('GtkWidgetPath')) +```lua +assert(Gtk.Window == GObject.Type.type('GtkWindow')) +assert(Gtk.WidgetPath == GObject.Type.type('GtkWidgetPath')) +``` When transferring `GType` value from Lua to C (e.g. calling function which accepts argument of `GType`), it is possible to use either @@ -766,22 +860,32 @@ string with type name, number representing numeric `GType` value, or any loaded component which has its type assigned. Some examples of `GType` usage follow: - lgi = require 'lgi' - GObject = lgi.GObject - Gtk = lgi.Gtk - - print(GObject.Type.NONE) - print(GObject.Type.name(GObject.Type.NONE)) - -- prints "void" in both cases - - print(GObject.Type.name(Gtk.Window)) - -- prints "GtkWindow" - - print(GObject.Type.is_a(Gtk.Window, GObject.Type.OBJECT)) - -- prints "true" - - print(GObject.Type.parent(Gtk.Window)) - -- prints "GtkBin" +```lua +lgi = require 'lgi' +GObject = lgi.GObject +Gtk = lgi.Gtk +``` + +```lua +print(GObject.Type.NONE) +print(GObject.Type.name(GObject.Type.NONE)) +-- prints "void" in both cases +``` + +```lua +print(GObject.Type.name(Gtk.Window)) +-- prints "GtkWindow" +``` + +```lua +print(GObject.Type.is_a(Gtk.Window, GObject.Type.OBJECT)) +-- prints "true" +``` + +```lua +print(GObject.Type.parent(Gtk.Window)) +-- prints "GtkBin" +``` ### 9.2. GObject.Value @@ -798,14 +902,18 @@ The call has two optional arguments, specifying `GType` of newly created `GValue` and optionally also the contents of the value. A few examples for creating new values follow: - local lgi = require 'lgi' - local GObject = lgi.GObject - local Gtk = lgi.Gtk +```lua +local lgi = require 'lgi' +local GObject = lgi.GObject +local Gtk = lgi.Gtk +``` - local empty = GObject.Value() - local answer = GObject.Value(GObject.Type.INT, 42) - local null_window = GObject.Value(Gtk.Window) - local window = GObject.Value(Gtk.Window, Gtk.Window()) +```lua +local empty = GObject.Value() +local answer = GObject.Value(GObject.Type.INT, 42) +local null_window = GObject.Value(Gtk.Window) +local window = GObject.Value(Gtk.Window, Gtk.Window()) +``` #### 9.2.2. Boxing and unboxing GObject.Value instances @@ -821,19 +929,23 @@ contents, it also converts contents to the new type (using `g_value_transform()`). Examples here continue using the values created in previous section example: - assert(empty.gtype == nil) - assert(empty.value == nil) - assert(answer.gtype == GObject.Type.INT) - assert(answer.value == 42) - assert(null_window.gtype == 'GtkWindow') - assert(null_window.value == nil) - - empty.gtype = answer.gtype - empty.value = 1 - assert(empty.gtype == GObject.Type.INT) - assert(empty.value == 1) - answer.gtype = GObject.Type.STRING) - assert(answer.value == '42') +```lua +assert(empty.gtype == nil) +assert(empty.value == nil) +assert(answer.gtype == GObject.Type.INT) +assert(answer.value == 42) +assert(null_window.gtype == 'GtkWindow') +assert(null_window.value == nil) +``` + +```lua +empty.gtype = answer.gtype +empty.value = 1 +assert(empty.gtype == GObject.Type.INT) +assert(empty.value == 1) +answer.gtype = GObject.Type.STRING) +assert(answer.value == '42') +``` Although `GObject.Value` provides most of the GValue documented methods (e.g. `g_value_get_string()` is accessible as @@ -847,7 +959,9 @@ Similar to GObject.Value, no automatic GClosure boxing is implemented. To create a new instance of `GClosure`, 'call' closure type and provide Lua function as an argument: - closure = GObject.Closure(func) +```lua +closure = GObject.Closure(func) +``` When the closure is emitted, a Lua function is called, getting `GObject.Value` as arguments and expecting to return `GObject.Value`