The cplus module provides additional canvas-related functions
that can be useful when writing scripts with a graphical user interface.
See Modules/cplus/init.lua
for the implementation details.
Graphics functions
Text functions
User interface functions
Some useful tables
Adjustable settings
The examples below assume a script has included this line:
local cp = require "cplus"
Graphics functions
cp.fill_ellipse(x, y, w, h, borderwd, fillrgba)
Draw an ellipse (or circle) inside the given rectangle.
If borderwd is greater than zero then an antialiased ellipse of the given thickness
is drawn using the current color.
If fillrgba is not an empty table then the ellipse is filled with the given color.
Example: cp.fill_ellipse(200, 450, 140, 99, 2, {255,255,0,200})
cp.round_rect(x, y, w, h, radius, borderwd, fillrgba)
Draw a rounded rectangle where the given radius determines the curvature of each corner.
If borderwd is greater than zero then an antialiased border of the given thickness
is drawn using the current color.
If fillrgba is not an empty table then the rectangle is filled with the given color.
Example: cp.round_rect(200, 300, 60, 30, 15, 0, {255,0,0,128})
Text functions
cp.minbox(clipname, wd, ht)
Find the minimal bounding box of non-transparent pixels in the given clip.
This can be used to determine the real dimensions of some text.
If all pixels in the clip are transparent then the returned values are all zero.
Example: local minx, miny, minwd, minht = cp.minbox("textclip", 80, 10)
cp.maketext(text, clipname, color, shadowx, shadowy, shadowcolor)
A simpler and more powerful way of creating text that can then be drawn with pastetext.
Only the first argument, text, is required.
Example:
-- draw the string "Hello World" at 0, 0 on the current render target
cp.maketext("Hello World")
cp.pastetext(0, 0)
Usually the text clip is created using the current rgba values. This can be
overridden by specifying the color argument.
The text may also be given a shadow at a specific x, y pixel offset defined with the shadowx
and shadowy arguments. The shadow will be drawn in opaque black unless a different color is
specified with the shadowcol argument.
Example:
-- create a clip named "hello" with the text "Hello World" in blue with a yellow shadow offset by -1, -2 pixels.
local w, h = cp.maketext("Hello World", "hello", cp.blue, -1, -2, cp.yellow)
The function returns the width and height of the created clip (including any shadow).
cp.pastetext(x, y, transform, clipname)
Paste text onto the current render target. Only the first two arguments x, y are required.
Returns the clip name.
Example:
-- paste a text clip at 0, 0 on the current render target
local textclip = cp.pastetext(0, 0)
The transform argument can be used to specify an affine transformation.
The clipname may be used to specify a non-default clipname.
Example:
-- paste the clip named "hello" at 0, 0 and rotated clockwise
cp.pastetext(0, 0, cp.rcw, "hello")
User interface functions
cp.button(label, onclick, args)
Create and return a table representing a button.
The button width depends on the given label text.
If the cp.process function detects a click in this
button then the given onclick function will be called with optional arguments.
If supplied, args must be a table (the table will be unpacked
and the results passed to the onclick function).
Example: cancel_button = cp.button("Cancel", glu.exit, {"bye bye"})
The button will only appear after its show function is called.
Example: cancel_button.show(10, 10)
cp.checkbox(label, onclick)
Create and return a table representing a check box.
The label text will be drawn to the right of a tickable button.
If the cp.process function detects a click in this
check box (including the label) then the given onclick function will be called.
Example: line_box = cp.checkbox("Show lines", ToggleLines)
The check box will only appear after its show function is called.
Example: line_box.show(10, 40, true)
cp.radiobutton(label, onclick)
Create and return a table representing a radio button.
The label text will be drawn to the right of a radio button.
If the cp.process function detects a click in this
radio button (including the label) then the given onclick function will be called.
Example:
draw_option = cp.radiobutton("Draw", SetDrawMode)
select_option = cp.radiobutton("Select", SetSelectMode)
move_option = cp.radiobutton("Move", SetMoveMode)
The radio button will only appear after its show function is called.
Example:
draw_option.show(10, 40, mode == "draw")
select_option.show(10, 40, mode == "select")
move_option.show(10, 40, mode == "move")
cp.slider(barwidth, minval, maxval, onclick)
Create and return a table representing a slider.
The bar width must be greater than 0.
The minimum and maximum values of the slider can be any integer values,
as long as minval is less than maxval.
If the cp.process function detects a click in this slider,
and the slider value has changed, then the given onclick function will be called
with two arguments: the new value and the slider table.
Example: red_slider = cp.slider(64, 0, 255, ColorChanged)
The slider will only appear after its show function is called.
Example: red_slider.show(10, 70, 255)
cp.menubar()
Create and return a table representing a menu bar.
You can then use its addmenu function to add menus to the menu bar,
then the additem function to append items to these menus.
If the cp.process function detects a click in this menu bar
then it will track the mouse and call the specified callback function if a menu item
is selected.
Example:
mbar = cp.menubar()
-- add some menus
mbar.addmenu("File")
mbar.addmenu("Edit")
-- add items to File menu
mbar.additem(1, "New File", NewFile)
mbar.additem(1, "Open File...", OpenFile)
mbar.additem(1, "Save File...", SaveFile)
mbar.additem(1, "---", nil) -- separator
mbar.additem(1, "Exit", glu.exit)
-- add items to Edit menu
mbar.additem(2, "Undo", Undo)
mbar.additem(2, "Redo", Redo)
The menu bar will appear when its show function is called.
Menu items can be enabled or disabled using the enableitem function,
and ticked or unticked using the tickitem function.
Example:
mbar.enableitem(2, 1, CanUndo())
mbar.enableitem(2, 2, CanRedo())
mbar.show(0, 0, 600, 30)
cp.process(event)
Process the given event (normally the string returned by getevent).
If it detects an unmodified left-click in a menu bar, button, check box, radio button or slider then
it will call the appropriate onclick function and return an empty string to
indicate the event was handled, otherwise it returns a copy of the given string
so the caller can process the event.
Example: local event = cp.process( glu.getevent() )
cp.disable_all()
Use this call to prevent cp.process from detecting clicks
in any existing menu bars, buttons, check boxes, radio buttons or sliders.
This is typically followed by a matching cp.enable_all
call at some later time.
See the dialogs.lua code for
how these calls are used to help implement a custom modal dialog.
Example: cp.disable_all()
cp.enable_all()
Use this call to undo the effects of the most recent cp.disable_all call.
Clicks in the menu bars, buttons, check boxes, radio buttons or sliders
that were disabled will now be detected.
Example: cp.enable_all()
cp.popupmenu()
Create and return a table representing a pop-up menu.
You can then use its additem function to append an item with a given label
and a callback function that will be called if the user selects the item.
Example:
editmenu = cp.popupmenu()
editmenu.additem("Cut", CutSelection)
editmenu.additem("Copy", CopySelection)
editmenu.additem("Clear", ClearSelection)
editmenu.additem("---", nil)
editmenu.additem("Paste", PasteClipboard)
The pop-up menu will appear when its show function is called.
If necessary, the menu's position is automatically adjusted
to ensure the entire menu is visible within the canvas.
Example:
editmenu.setbackcolor{0,128,0,255} -- dark green background
editmenu.show(mousex, mousey)
Some useful tables
The cplus module defines a number of tables for use in various functions.
Opaque colors:
cp.white | | = {255,255,255,255} |
cp.gray | | = {128,128,128,255} |
cp.black | | = {0,0,0,255} |
cp.red | | = {255,0,0,255} |
cp.green | | = {0,255,0,255} |
cp.blue | | = {0,0,255,255} |
cp.cyan | | = {0,255,255,255} |
cp.magenta | | = {255,0,255,255} |
cp.yellow | | = {255,255,0,255} |
Affine transformations:
cp.identity | | = {1,0,0,1} |
cp.flip | | = {-1,0,0,-1} |
cp.flip_x | | = {-1,0,0,1} |
cp.flip_y | | = {1,0,0,-1} |
cp.swap_xy | | = {0,1,1,0} |
cp.swap_xy_flip | | = {0,-1,-1,0} |
cp.rcw | | = {0,-1,1,0} |
cp.rccw | | = {0,1,-1,0} |
cp.racw | | = cp.rccw |
cp.r180 | | = cp.flip |
Adjustable settings
The cplus module has a number of settings that control the appearance
of buttons, menus, etc. Scripts can easily change these settings, as in the
following examples:
cp.buttonht = 30 | |
-- height of buttons |
cp.radius = 5 | |
-- curvature of button corners |
cp.border = 3 | |
-- thickness of button border (no border if 0) |
cp.menubg = {40,40,40,255} | |
-- dark gray background for menu bar and items |
cp.menufont = "mono-bold" | |
-- font for menu and item text |
cp.menufontsize = 11 | |
-- font size for menu and item text |
A complete list of the settings you might want to adjust can be seen near the start of
init.lua.