Ipelib: Lua bindings for dialogs and menus

Ipelib

Lua bindings for dialogs and menus

The ipeui module provides dialogs and popup menus for Lua. It does not depend on any other Ipe component, and can be reused in other Lua projects.

# Global methods

There are a few global methods in the ipeui module:

    ipeui.startBrowser(url)   -- on Win32 and Cocoa only
    dt = ipeui.currentDateTime() -- returns string with current date and time

# Predefined dialogs

The following are predefined dialogs. In all cases, `parent` can either be `nil` or a Window ID.

## File dialog

Ask the user to select a filename for opening or for saving. 'type' is "open" or "save". 'filter' is a table with the file name filters. Each filter has two entries in the table, one with the name of the filter and the extensions in parenthesis (this is used by Qt), one with the pure patterns separated by semicolons (this is also used by Windows). Here is an example:

    filter_save = { "XML (*.ipe *.xml)", "*.ipe;*.xml",
                    "PDF (*.pdf)", "*.pdf" }

'dir' is the initially selected directory, or nil.

'name' is an initial name (without path) to show as the filename, or nil.

'selected' is the number of the initally selected file name filter (where 1 is the first filter), or nil.

The funtion returns nil, or both a file name and the number of the selected filter.

    ipeui.fileDialog(parent, type, caption, filter, dir, name, selected)

## Color dialog

    -- choose a color
    -- r,g,b are in the range 0.0 to 1.0
    -- returns nil or a (r,g,b) triple
    ipeui.getColor(parent, title, r, g, b)

## Message box

    -- show a message box
    -- type is one of "none" "warning" "information" "question" "critical"
    -- details may be nil
    -- buttons may be nil (for "ok") or one of
    -- "ok" "okcancel" "yesnocancel", "discardcancel", "savediscardcancel",
    -- return 1 for ok/yes/save, 0 for no/discard, -1 for cancel
    ipeui.messageBox(parent, type, text, details, buttons)

## Wait dialog

This dialog executes an external program. The function returns only after the external program has finished executing.

    ipeui.waitDialog(parent, command)

# Dialogs

Other dialogs can be constructed programmatically. A dialog consists of various elements layed out in a grid, and a row of buttons underneath. Create the dialog by adding elements using 'add', and filling the button row using 'addButton'. The 'action' for 'addButton' can be one of the strings "accept" or "reject", or a Lua method.

    d = ipeui.Dialog(parent, window_title)

    -- row == -1 means last row, row == 0 means start new row
    d:add(name, what, options, row, column, row_span, column_span)
    d:addButton(name, caption, action)

    d:setStretch("row", row_number, stretch_factor)
    d:setStretch("column", column_number, stretch_factor)

    d:set(name, value)
    value = d:get(name)

    -- enable/disable elements
    d:setEnabled(name, true_or_false)

    -- set whether escape should be ignored (true/false)
    d:set("ignore-escape", flag)

    -- returns true if dialog was accepted
    d:execute()
    d:execute(size)   -- where size == { width, height }

name can be an arbitrary string. what must be one of

    button, text, list, label, combo, checkbox, input

options is a table. Most fields are optional:

    -- button:
    label="string"  (Required!)
    action="accept" or "reject" or a Lua method

    -- label:
    label="string"  (Required!)

    -- text:
    read_only=bool
    syntax="logfile" or "xml" or "latex"
    select_all=bool
    spell_check=bool

    -- list and combo:
    array of list items (strings)
    can also contain a Lua method with key "action" (called when an item
    is activated).

    -- checkbox:
    label="string"  (Required!)
    action= Lua method  (called when state changed)

    -- input:

The Lua method for button, checkbox, combo, and list is called with the dialog as an argument. Do not capture the dialog inside the method, as this would create a cyclic reference that would stop the dialog from being garbage collected! (It also causes a crash on Qt if the dialog is destroyed by Lua after the parent window has already deleted it.)

The argument of set is:

- a string value for label, text, and input,
- either an integer, a string, or an array of string items for list and combo,
- a boolean for checkbox.

The result value of get is:

- a string for text and input,
- an integer for list (or nil if there is no current item) and combo,
- a boolean for checkbox.

# Popup menus

Popup menus are constructed and shown as follows:

    m = ipeui.Menu(parent)
    item, no, subitem = m:execute(global_position)

When the menu is cancelled, execute returns nil.

You can then add items to the menu one by one. A simple item is added like this:

    m:add("name", "Label")

When this item is selected, execute returns name, 0, and an empty string.

The following line adds an entire submenu:

    m:add("name", "Submenu", { "alpha", "beta", "gamma" } )

When an item from this submenu is selected, execute returns name, the index into the submenu, and the name of the submenu item.

When the strings in the table are not directly the visible labels for the submenu, a Lua function can be used to convert them:

    m:add("name", "Submenu", { "alpha", "beta", "gamma" },
          function (i, item) return "select " .. item end )

The final argument can either be a string or a function. If it is a string, then all items are checkable, and the item whose name is identical to the final argument is checked. Otherwise, the function maps item number and name to a color (three numbers in the range 0.0 to 1.0). This is then used to display a color icon.

# Timers

Timers are constructed as follows:

    t = ipeui.Timer(table, "method")

When the timer times out, it will call the method named method in the Lua table table. The timer stores only a weak reference to the table, so the timer will not stop the table from being garbage collected.

The timer is controlled using the methods:

    timer:setInterval(interval)     -- an integer in milliseconds
    timer:setSingleShot(bool)       -- default is repeating timer
    timer:start()
    timer:stop()
    a = timer:active()              -- true if the timer is running