├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── README.md ├── examples ├── controlgallery.lua ├── datetime.lua ├── drawtext.lua ├── hello.lua ├── histogram.lua ├── multithread.lua └── timer.lua ├── src ├── enum.c ├── larea.c ├── lattribute.c ├── lattributedstr.c ├── lbox.c ├── lbutton.c ├── lcheckbox.c ├── lcolorbutton.c ├── lcombobox.c ├── lcontrol.c ├── ldatetimerpicker.c ├── ldraw.c ├── lentry.c ├── lfontbutton.c ├── lform.c ├── lgrid.c ├── lgroup.c ├── limage.c ├── llabel.c ├── lmenu.c ├── lmenuitem.c ├── lmultiline.c ├── lprogressbar.c ├── lradiobuttons.c ├── lseparator.c ├── lslider.c ├── lspinbox.c ├── ltab.c ├── ltable.c ├── lui.c ├── lui.h └── lwindow.c └── test.lua /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | *.su 34 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "deps/lua-compat-5.3"] 2 | path = deps/compat 3 | url = https://github.com/keplerproject/lua-compat-5.3.git 4 | [submodule "deps/auxiliar"] 5 | path = deps/auxiliar 6 | url = https://github.com/zhaozg/lua-auxiliar 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2018 George Zhao 2 | Copyright (c) 2016 Ico Doornekamp 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | 10 | (this is called the MIT License or Expat License; see http://www.opensource.org/licenses/MIT) 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | T=lui 2 | 3 | PREFIX ?=/usr/local 4 | CC := $(CROSS)$(CC) 5 | AR := $(CROSS)$(AR) 6 | LD := $(CROSS)$(LD) 7 | 8 | #OS auto detect 9 | ifneq (,$(TARGET_SYS)) 10 | SYS := $(TARGET_SYS) 11 | else 12 | SYS := $(shell gcc -dumpmachine) 13 | endif 14 | 15 | #Lua auto detect 16 | ifneq (iOS,$SYS) 17 | LUA_VERSION ?= $(shell pkg-config luajit --print-provides) 18 | ifeq ($(LUA_VERSION),) 19 | ############ use lua 20 | LUAV ?= $(shell lua -e "_,_,v=string.find(_VERSION,'Lua (.+)');print(v)") 21 | LUA_CFLAGS ?= -I$(PREFIX)/include/lua$(LUAV) 22 | LUA_LIBS ?= -L$(PREFIX)/lib 23 | LUA_LIBDIR ?= $(PREFIX)/lib/lua/$(LUAV) 24 | else 25 | ############ use luajit 26 | LUAV ?= $(shell luajit -e "_,_,v=string.find(_VERSION,'Lua (.+)');print(v)") 27 | LUA_CFLAGS ?= $(shell pkg-config luajit --cflags) 28 | LUA_LIBS ?= $(shell pkg-config luajit --libs) 29 | LUA_LIBDIR ?= $(PREFIX)/lib/lua/$(LUAV) 30 | endif 31 | else 32 | LUA_CFLAGS ?= $(shell pkg-config luajit --cflags) 33 | LUA_LIBS ?= $(shell pkg-config luajit --libs) 34 | endif 35 | 36 | #libui auto detect 37 | LIBUI_PREFIX ?= /usr/local 38 | LIBUI_CFLAGS ?= -I$(LIBUI_PREFIX)/include 39 | LIBUI_LIBS ?= -L$(LIBUI_PREFIX)/lib -lui 40 | 41 | ifneq (, $(findstring linux, $(SYS))) 42 | # Do linux things 43 | CFLAGS += -fpic 44 | LDFLAGS += -Wl,--no-undefined -fpic -lrt -ldl -lm 45 | endif 46 | ifneq (, $(findstring apple, $(SYS))) 47 | # Do darwin things 48 | CFLAGS += -fPIC 49 | LDFLAGS += -fPIC -undefined dynamic_lookup -ldl 50 | MACOSX_DEPLOYMENT_TARGET="10.8" 51 | CC := MACOSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET} $(CC) 52 | endif 53 | ifneq (, $(findstring mingw, $(SYS))) 54 | # Do mingw things 55 | CFLAGS += -DLUA_LIB -DLUA_BUILD_AS_DLL -DWIN32_LEAN_AND_MEAN 56 | endif 57 | ifneq (, $(findstring cygwin, $(SYS))) 58 | # Do cygwin things 59 | CFLAGS += -fPIC 60 | endif 61 | ifneq (, $(findstring iOS, $(SYS))) 62 | # Do iOS things 63 | CFLAGS += -fPIC 64 | LDFLAGS += -fPIC -ldl 65 | endif 66 | 67 | #custom config 68 | ifeq (.config, $(wildcard .config)) 69 | include .config 70 | endif 71 | 72 | LIBNAME= $T.so.$V 73 | LUA_CFLAGS += -Ideps/lua-compat-5.3 74 | CFLAGS += $(LIBUI_CFLAGS) $(LUA_CFLAGS) $(TARGET_FLAGS) 75 | LDFLAGS += -shared $(LIBUI_LIBS) $(LUA_LIBS) 76 | # Compilation directives 77 | WARN_MIN = -Wall -Wno-unused-value 78 | WARN = -Wall 79 | WARN_MOST = $(WARN) -W -Waggregate-return -Wcast-align -Wmissing-prototypes -Wnested-externs -Wshadow -Wwrite-strings -pedantic 80 | CFLAGS += $(WARN_MIN) -DPTHREADS -Ideps -Ideps/compat -Ideps/auxiliar 81 | 82 | all: $T.so 83 | @echo "Target system: "$(SYS) 84 | 85 | $T.so: src/*.c deps/auxiliar/auxiliar.c 86 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ src/lui.c deps/auxiliar/auxiliar.c 87 | 88 | install: all 89 | mkdir -p $(LUA_LIBDIR) 90 | cp $T.so $(LUA_LIBDIR) 91 | 92 | info: 93 | @echo "Target system: "$(SYS) 94 | @echo "CC:" $(CC) 95 | @echo "AR:" $(AR) 96 | @echo "PREFIX:" $(PREFIX) 97 | 98 | clean: 99 | rm -rf $T.so* 100 | 101 | # vim: ts=8 sw=8 noet 102 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lui, libui bare bindings for lua 2 | 3 | [libui](https://github.com/andlabs/libui) bare bindings for 4 | [luajit](http://luajit.org/) and [lua](http://www.lua.org/) 5 | [5.1](http://www.lua.org/manual/5.1/manual.html)/ 6 | [5.2](http://www.lua.org/manual/5.2/manual.html)/ 7 | [5.3](http://www.lua.org/manual/5.3/manual.html). 8 | 9 | This binding makes libui available to lua scripts. libui is easy binding and should usable from nearly any lua project. 10 | 11 | ## Notice 12 | 13 | - Because lua is missing native threads support, so threads feature maybe lost. 14 | - Because libui/lui is not mature enough, you maybe encounter strange bugs. 15 | 16 | ## Examples 17 | 18 | Examples can be found in the [examples](examples) folders, those are translate from [examples](https://github.com/andlabs/libui/tree/master/examples). 19 | 20 | ## Buliding 21 | 22 | ### Checkout source 23 | 24 | ```shell 25 | git checkout https://github.com/zhaozg/lui.git 26 | cd lui 27 | git submodule init 28 | git submodule update 29 | ``` 30 | 31 | ### Building on linux or macOS 32 | 33 | ```shell 34 | cd lui 35 | make install 36 | ``` 37 | 38 | ### Building on Windows 39 | 40 | TODO 41 | 42 | ### APIs 43 | 44 | - All top level functions are in the table returned by `require` 45 | 46 | ```lua 47 | ui = require'lui' -- type(ui) is 'table' 48 | ``` 49 | 50 | - All module level uiXXXX() functions are accessible as ui.XXXX(), they are include 51 | - `Init` 52 | - `Uninit` 53 | - `Main` 54 | - `MainStep` 55 | - `MainSteps` 56 | - `timer` 57 | - `Quit` 58 | - `QueueMain` 59 | - `OnShouldQuit` 60 | - `OpenFile` 61 | - `SaveFile` 62 | - `MsgBox` 63 | - `MsgBoxError`. 64 | 65 | ```lua 66 | assert(ui.Init()) 67 | ui.Quit() 68 | ui.Uninit() 69 | ``` 70 | 71 | - New objects are created with ui.NewXXX() or ui.DrawNewXXXX(), the are include 72 | - `NewArea` 73 | - `NewButton` 74 | - `NewCheckbox` 75 | - `NewCombobox` 76 | - `NewColorButton` 77 | - `NewDateTimePicker` 78 | - `NewDatePicker` 79 | - `NewEditableCombobox` 80 | - `NewEntry` 81 | - `NewFontButton` 82 | - `NewForm` 83 | - `NewGrid` 84 | - `NewGroup` 85 | - `NewHorizontalBox` 86 | - `NewHorizontalSeparator` 87 | - `NewLabel` 88 | - `NewMenu` 89 | - `NewMultilineEntry` 90 | - `NewNonWrappingMultilineEntry` 91 | - `NewPasswordEntry` 92 | - `NewProgressBar` 93 | - `NewRadioButtons` 94 | - `NewSearchEntry` 95 | - `NewSlider` 96 | - `NewSpinbox` 97 | - `NewTimePicker` 98 | - `NewTab` 99 | - `NewVerticalBox` 100 | - `NewVerticalSeparator` 101 | - `NewWindow` 102 | - `DrawNewAreaHandler` 103 | - `DrawNewBrush` 104 | - `DrawNewPath` 105 | - `DrawNewMatrix` 106 | - `DrawNewStrokeParams` 107 | - `DrawNewTextLayout` 108 | - `DrawListFontFamilies` (Special) 109 | - `DrawLoadClosestFont` (Special) 110 | 111 | ```lua 112 | wnd = ui.NewWindow(...) -- type(wnd) is userdata with metatable 'libui.Window' 113 | ``` 114 | 115 | - All object perperties like uiTypeValue() and uiTypeSetValue() are accessible as obj:Value() 116 | 117 | ```lua 118 | entry:Padded(true) -- just call uiEntrySetPadded(entry,1) and return object itself 119 | entry:Padded() -- just call uiEntryPadded(entry) and return boolean type padded value 120 | ``` 121 | 122 | - Object Append() methods take a variable number of arguments, allowing things 123 | 124 | ```lua 125 | `ui.NewRadioButtons():Append("One", "Two", "Three") 126 | ``` 127 | 128 | - All object functions like uiTypeMethod() are accessible as obj:Method() calls 129 | 130 | ```lua 131 | wnd:Show() 132 | wnd:OnClosing(onclosing_cb) 133 | ``` 134 | 135 | You need read [examples](examples) to be familiar with them. 136 | 137 | ## Thanks 138 | 139 | - [Ico Doornekamp](https://github.com/zevv) lui basicly forked of [libuilua](https://github.com/zevv/libuilua) but updated. 140 | - [Pietro Gagliardi](https://github.com/andlabs) author of [libui](https://github.com/andlabs/libui). 141 | -------------------------------------------------------------------------------- /examples/controlgallery.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | 3 | local ui = require "lui" 4 | 5 | local function onClosing(w) 6 | ui.Quit() 7 | return true 8 | end 9 | 10 | local function onShouldQuit(mw) 11 | ui.ControlDestroy(mw) 12 | return true 13 | end 14 | 15 | local function makeBasicControlsPage() 16 | local vbox, hbox, group, entryForm 17 | 18 | vbox = ui.NewVerticalBox():Padded(true) 19 | hbox = ui.NewHorizontalBox():Padded(true) 20 | 21 | vbox:Append(hbox,false) 22 | hbox:Append(ui.NewButton("Button"),false) 23 | :Append(ui.NewCheckbox("Checkbox"),false) 24 | 25 | vbox:Append(ui.NewLabel("This is a label. Right now, labels can only span one line."),false) 26 | :Append(ui.NewHorizontalSeparator(),false) 27 | 28 | group = ui.NewGroup("Entries"):Margined(true) 29 | vbox:Append(group,true) 30 | 31 | entryForm = ui.NewForm():Padded(true) 32 | group:SetChild(entryForm) 33 | entryForm:Append('Entry',ui.NewEntry(),false) 34 | :Append('Password Entry', ui.NewPasswordEntry(), false) 35 | :Append('Search Entry', ui.NewSearchEntry(), false) 36 | :Append('Multiline Entry', ui.NewMultilineEntry(), true) 37 | return vbox 38 | end 39 | 40 | local spinbox, slider, pbar 41 | 42 | local function onSpinboxChanged(s, data) 43 | slider:Value(s:Value()) 44 | pbar:Value(s:Value()) 45 | end 46 | 47 | local function onSliderChanged(s, data) 48 | spinbox:Value(s:Value()) 49 | pbar:Value(s:Value()) 50 | end 51 | 52 | local function makeNumbersPage() 53 | local hbox, group, vbox, ip, cbox, ecbox, rb 54 | 55 | hbox = ui.NewHorizontalBox():Padded(true) 56 | group = ui.NewGroup("Numbers"):Margined(true) 57 | hbox:Append(group,true) 58 | 59 | vbox = ui.NewVerticalBox():Padded(true) 60 | group:SetChild(vbox) 61 | 62 | spinbox = ui.NewSpinbox(0, 100):OnChanged(onSpinboxChanged) 63 | slider = ui.NewSlider(0, 100):OnChanged(onSliderChanged); 64 | pbar = ui.NewProgressBar(); 65 | vbox:Append(spinbox) 66 | :Append(slider) 67 | :Append(pbar) 68 | 69 | ip = ui.NewProgressBar():Value(-1) 70 | vbox:Append(ip) 71 | 72 | group = ui.NewGroup("Lists"):Margined(true) 73 | hbox:Append(group) 74 | 75 | vbox = ui.NewVerticalBox():Padded(true) 76 | group:SetChild(vbox) 77 | 78 | cbox = ui.NewCombobox() 79 | :Append("Combobox Item 1") 80 | :Append("Combobox Item 2") 81 | :Append("Combobox Item 3") 82 | vbox:Append(cbox,false) 83 | 84 | ecbox = ui.NewEditableCombobox() 85 | :Append("Editable Item 1") 86 | :Append("Editable Item 2") 87 | :Append("Editable Item 3") 88 | vbox:Append(ecbox,false) 89 | 90 | rb = ui.NewRadioButtons() 91 | :Append("Radio Button 1") 92 | :Append("Radio Button 2") 93 | :Append("Radio Button 3") 94 | vbox:Append(rb, false) 95 | return hbox 96 | end 97 | 98 | local mainwin 99 | 100 | local function onOpenFileClicked(b, entry) 101 | local filename = ui.OpenFile(mainwin) 102 | if (filename == nil) then 103 | entry:Text("(cancelled)"); 104 | return; 105 | end 106 | entry:Text(filename) 107 | end 108 | 109 | local function onSaveFileClicked(b, entry) 110 | local filename = ui.SaveFile(mainwin) 111 | if (filename == nil) then 112 | entry:Text("(cancelled)") 113 | return 114 | end 115 | entry:Text(filename) 116 | end 117 | 118 | local function onMsgBoxClicked(b) 119 | ui.MsgBox(mainwin, 120 | "This is a normal message box.", 121 | "More detailed information can be shown here.") 122 | end 123 | 124 | local function onMsgBoxErrorClicked(b) 125 | ui.MsgBoxError(mainwin, 126 | "This message box describes an error.", 127 | "More detailed information can be shown here.") 128 | end 129 | 130 | local function makeDataChoosersPage() 131 | local hbox, vbox, grid, button, entry, msggrid 132 | 133 | hbox = ui.NewHorizontalBox():Padded(true) 134 | vbox = ui.NewVerticalBox():Padded(true) 135 | hbox:Append(vbox, false) 136 | 137 | vbox:Append(ui.NewDatePicker(),false) 138 | :Append(ui.NewTimePicker(),false) 139 | :Append(ui.NewDateTimePicker(), false) 140 | :Append(ui.NewFontButton(),false) 141 | :Append(ui.NewColorButton(),false) 142 | 143 | hbox:Append(ui.NewVerticalSeparator(),false) 144 | 145 | vbox = ui.NewVerticalBox() 146 | :Padded(true) 147 | hbox:Append(vbox, true) 148 | 149 | grid = ui.NewGrid():Padded(true) 150 | vbox:Append(grid,false) 151 | 152 | button = ui.NewButton("Open File") 153 | entry = ui.NewEntry():ReadOnly(true) 154 | button:OnClicked(onOpenFileClicked, entry) 155 | grid:Append(button, 156 | 0, 0, 1, 1, 157 | false, ui.AlignFill, false, ui.AlignFill) 158 | grid:Append(entry, 159 | 1, 0, 1, 1, 160 | true, ui.AlignFill, false, ui.AlignFill) 161 | 162 | button = ui.NewButton("Save File") 163 | entry = ui.NewEntry():ReadOnly(true) 164 | button:OnClicked(onSaveFileClicked, entry); 165 | grid:Append(button, 166 | 0, 1, 1, 1, 167 | false, ui.AlignFill, false, ui.AlignFill) 168 | grid:Append(entry, 169 | 1, 1, 1, 1, 170 | true, ui.AlignFill, false, ui.AlignFill) 171 | 172 | msggrid = ui.NewGrid():Padded(true) 173 | grid:Append(msggrid, 174 | 0, 2, 2, 1, 175 | false, ui.AlignCenter, false, ui.AlignStart) 176 | 177 | button = ui.NewButton("Message Box"):OnClicked(onMsgBoxClicked) 178 | msggrid:Append(button, 179 | 0, 0, 1, 1, 180 | false, ui.AlignFill, false, ui.AlignFill); 181 | button = ui.NewButton("Error Box"):OnClicked(onMsgBoxErrorClicked) 182 | msggrid:Append(button, 183 | 1, 0, 1, 1, 184 | false, ui.AlignFill, false, ui.AlignFill); 185 | 186 | return hbox 187 | end 188 | 189 | local function uiMain() 190 | local ret,err = ui.Init(); 191 | if (not ret) then 192 | io.stderr:write(string.format("error initializing libui: %s", err)); 193 | return 1; 194 | end 195 | 196 | mainwin = ui.NewWindow("libui Control Gallery", 640, 480, true) 197 | :OnClosing(onClosing); 198 | ui.OnShouldQuit(onShouldQuit, mainwin); 199 | 200 | tab = ui.NewTab(); 201 | mainwin:SetChild(tab):Margined(true) 202 | tab:Append("Basic Controls", makeBasicControlsPage()):Margined(0, true); 203 | tab:Append("Numbers and Lists", makeNumbersPage()):Margined(1, true) 204 | tab:Append("Data Choosers", makeDataChoosersPage()):Margined(2, true) 205 | 206 | mainwin:Show() 207 | ui.Main() 208 | ui.Uninit() 209 | 210 | return 0; 211 | end 212 | 213 | uiMain() 214 | -------------------------------------------------------------------------------- /examples/datetime.lua: -------------------------------------------------------------------------------- 1 | local ui = require'lui' 2 | 3 | local dtboth, dtdate, dttime 4 | local function timeFormat(d) 5 | local fmt 6 | if (d == dtboth) then 7 | fmt = "%c" 8 | elseif (d == dtdate) then 9 | fmt = "%x" 10 | elseif (d == dttime) then 11 | fmt = "%X" 12 | else 13 | fmt = "%c" 14 | end 15 | return fmt 16 | end 17 | 18 | local function onChanged(d, l) 19 | local tm = d:Time() 20 | local s = os.time(tm) 21 | s = os.date(timeFormat(d), s) 22 | l:Text(s) 23 | end 24 | 25 | local function onClicked(b, data) 26 | if (data) then data = os.time() end 27 | local tm = os.date(data) 28 | 29 | dtdate:SetTime(tm) 30 | dttime:SetTime(tm) 31 | end 32 | 33 | function onClosing(w, data) 34 | ui.Quit() 35 | return 1 36 | end 37 | 38 | function main() 39 | local err, w, g, l, b 40 | ui.Init() 41 | 42 | w = ui.NewWindow("Date / Time", 320, 240, false):Margined(true) 43 | 44 | g = ui:NewGrid():Padded(true) 45 | w:SetChild(g) 46 | --[[ 47 | dtboth = ui.NewDateTimePicker() 48 | dtdate = ui.NewDatePicker() 49 | dttime = ui.NewTimePicker() 50 | 51 | g:Append(dtboth, 0, 0, 2, 0, true, ui.AlignFill, false, ui.AlignFill) 52 | 53 | g:Append(dtdate, 0, 1, 1, 1, true, ui.AlignFill, false, ui.AlignFill) 54 | g:Append(dttime, 1, 1, 1, 1, true, ui.AlignFill, false, ui.AlignFill) 55 | 56 | l = ui.NewLabel("") 57 | g:Append(l, 58 | 0, 2, 2, 1, 59 | true, ui.AlignFill, false, ui.AlignFill) 60 | dtboth:OnChanged(onChanged, l) 61 | 62 | l = ui.NewLabel("") 63 | g:Append(l, 64 | 0, 3, 1, 1, 65 | true, ui.AlignCenter, false, ui.AlignFill) 66 | dtdate:OnChanged(onChanged, l) 67 | 68 | l = ui.NewLabel("") 69 | g:Append(l, 70 | 1, 3, 1, 1, 71 | true, ui.AlignCenter, false, ui.AlignFill) 72 | dttime:OnChanged(onChanged, l) 73 | 74 | b = ui.NewButton("Now") 75 | b:OnClicked(onClicked, 1) 76 | g:Append(b, 77 | 0, 4, 1, 1, 78 | true, ui.AlignFill, true, ui.AlignEnd) 79 | b = ui.NewButton("Unix epoch") 80 | b:OnClicked(onClicked, 0) 81 | g:Append(b, 82 | 1, 4, 1, 1, 83 | true, ui.AlignFill, true, ui.AlignEnd) 84 | --]] 85 | w:OnClosing(onClosing):Show() 86 | ui.Main() 87 | ui.Uninit() 88 | return 0 89 | end 90 | 91 | main() 92 | -------------------------------------------------------------------------------- /examples/drawtext.lua: -------------------------------------------------------------------------------- 1 | local ui = require('lui') 2 | 3 | local mainwin, area, handler, fontButton, alignment, attrstr 4 | 5 | local function appendWithAttribute(what, attr, attr2) 6 | local start, ends 7 | 8 | start = attrstr:Len() 9 | ends = start + #what 10 | attrstr:AppendUnattributed(what) 11 | attrstr:SetAttribute(attr, start, ends) 12 | if (attr2 ) then 13 | attrstr:SetAttribute(attr2, start, ends) 14 | end 15 | end 16 | 17 | local function makeAttributedString() 18 | local attr, attr2, otf 19 | 20 | attrstr = ui.NewAttributedString([[ 21 | Drawing strings with libui is done with the attrstr: and uiDrawTextLayout objects. 22 | attrstr: lets you have a variety of attributes: ]]) 23 | 24 | attr = ui.NewAttribute("family", "Courier New") 25 | appendWithAttribute("font family", attr) 26 | attrstr:AppendUnattributed(", ") 27 | 28 | attr = ui.NewAttribute("size", 18) 29 | appendWithAttribute("font size", attr, NULL) 30 | attrstr:AppendUnattributed(", ") 31 | 32 | attr = ui.NewAttribute("weight", ui.TextWeightBold) 33 | appendWithAttribute("font weight", attr) 34 | attrstr:AppendUnattributed(", ") 35 | 36 | attr = ui.NewAttribute("italic", ui.TextItalicItalic) 37 | appendWithAttribute("font italicness", attr) 38 | attrstr:AppendUnattributed(", ") 39 | 40 | attr = ui.NewAttribute("stretch", ui.TextStretchCondensed) 41 | appendWithAttribute("font stretch", attr) 42 | attrstr:AppendUnattributed(", ") 43 | 44 | attr = ui.NewAttribute("color", 0.75, 0.25, 0.5, 0.75) 45 | appendWithAttribute("text color", attr) 46 | attrstr:AppendUnattributed(", ") 47 | 48 | attr = ui.NewAttribute("background", 0.5, 0.5, 0.25, 0.5) 49 | appendWithAttribute("text background color", attr) 50 | attrstr:AppendUnattributed(", ") 51 | 52 | 53 | attr = ui.NewAttribute("underline", ui.UnderlineSingle) 54 | appendWithAttribute("underline style", attr) 55 | attrstr:AppendUnattributed(", ") 56 | 57 | attrstr:AppendUnattributed("and ") 58 | attr = ui.NewAttribute("underline", ui.UnderlineDouble) 59 | attr2 = ui.NewAttribute("underlinecolor", ui.UnderlineColorCustom, 1.0, 0.0, 0.5, 1.0) 60 | appendWithAttribute("underline color", attr, attr2) 61 | attrstr:AppendUnattributed(". ") 62 | 63 | attrstr:AppendUnattributed("Furthermore, there are attributes allowing for ") 64 | attr = ui.NewAttribute("underline", ui.UnderlineSuggestion) 65 | attr2 = ui.NewAttribute("underlinecolor", ui.UnderlineColorSpelling, 0, 0, 0, 0) 66 | appendWithAttribute("special underlines for indicating spelling errors", attr, attr2) 67 | attrstr:AppendUnattributed(" (and other types of errors) ") 68 | 69 | attrstr:AppendUnattributed("and control over OpenType features such as ligatures (for instance, ") 70 | 71 | local l, i, g, a = string.byte('liga',1,4) 72 | otf = ui.NewOpenTypeFeatures() 73 | otf:Add(l, i, g, a, 0) 74 | attr = ui.NewAttribute('features', otf) 75 | appendWithAttribute("afford", attr) 76 | attrstr:AppendUnattributed(" vs. ") 77 | otf:Add(l, i, g, a, 1) 78 | attr = ui.NewAttribute('features', otf) 79 | appendWithAttribute("afford", attr) 80 | otf:Free() 81 | attrstr:AppendUnattributed(").\n") 82 | 83 | attrstr:AppendUnattributed("Use the controls opposite to the text to control properties of the text.") 84 | end 85 | 86 | function handlerDraw(a, area, p) 87 | local textLayout, defaultFont, params 88 | 89 | defaultFont = fontButton:Font() 90 | print(defaultFont) 91 | params = ui.DrawNewTextLayoutParams(attrstr, defaultFont, p.AreaWidth, alignment:Selected() ) 92 | textLayout = ui.DrawNewTextLayout(params) 93 | p.Context:Text(textLayout, 0, 0) 94 | textLayout:Free() 95 | defaultFont:Free() 96 | end 97 | 98 | function handlerMouseEvent(a, area, e) 99 | print('MouseEvent') 100 | end 101 | 102 | function handlerMouseCrossed(ah, a, left) 103 | print('MouseCrossed') 104 | end 105 | 106 | function handlerDragBroken(ah, a) 107 | print('DragBroken') 108 | end 109 | 110 | function handlerKeyEvent(ah, a, e) 111 | print('KeyEvent') 112 | return 0 113 | end 114 | 115 | function onFontChanged(b, data) 116 | area:QueueRedrawAll() 117 | end 118 | 119 | function onComboboxSelected(b, data) 120 | area:QueueRedrawAll() 121 | end 122 | 123 | function onClosing(w, data) 124 | ui.Quit() 125 | return true 126 | end 127 | 128 | function shouldQuit(data) 129 | mainwin:Destroy() 130 | return 1 131 | end 132 | 133 | function main() 134 | local err, hbox, vbox, form 135 | ui.Init() 136 | ui.OnShouldQuit(shouldQuit) 137 | 138 | handler = ui.DrawNewAreaHandler( 139 | handlerDraw, 140 | handlerMouseEvent, 141 | handlerMouseCrossed, 142 | handlerDragBroken, 143 | handlerKeyEvent) 144 | 145 | makeAttributedString() 146 | 147 | mainwin = ui.NewWindow("libui Text-Drawing Example", 640, 480, true) 148 | :Margined(true) 149 | :OnClosing(onClosing) 150 | 151 | hbox = ui.NewHorizontalBox() 152 | :Padded(true) 153 | mainwin:SetChild(hbox) 154 | 155 | vbox = ui.NewVerticalBox():Padded(true) 156 | hbox:Append(vbox, false) 157 | 158 | fontButton = ui.NewFontButton() 159 | :OnChanged(onFontChanged) 160 | vbox:Append(fontButton, false) 161 | 162 | form = ui.NewForm():Padded(true) 163 | --TODO on OS X if this is set to 1 then the window can't resize; does the form not have the concept of stretchy trailing space? 164 | vbox:Append(form, false) 165 | 166 | alignment = ui.NewCombobox() 167 | -- note that the items match with the values of the uiDrawTextAlign values 168 | alignment:Append("Left") 169 | :Append("Center") 170 | :Append("Right") 171 | :Selected(0) 172 | :OnSelected(onComboboxSelected) 173 | 174 | form:Append("Alignment", alignment, false) 175 | 176 | area = ui.NewArea(handler) 177 | hbox:Append(area, true) 178 | 179 | mainwin:Show() 180 | ui.Main() 181 | attrstr:Free() 182 | ui.Uninit() 183 | return 0 184 | end 185 | 186 | main() 187 | 188 | -------------------------------------------------------------------------------- /examples/hello.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | 3 | local ui = require "lui" 4 | local function onClosing(w, data) 5 | ui.Quit() 6 | return true 7 | end 8 | 9 | function uiMain(void) 10 | --init 11 | local ret, err = ui.Init() 12 | if not ret then 13 | error(err) 14 | end 15 | 16 | local w = ui.NewWindow("Hello", 320, 240, false) 17 | -- w:OnClosing(onClosing) 18 | w:Show() 19 | ui.Main() 20 | ui.Uninit() 21 | end 22 | 23 | uiMain() 24 | -------------------------------------------------------------------------------- /examples/histogram.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | 3 | local ui = require "lui" 4 | local bit = require'bit' 5 | 6 | local mainwin, histogram, handler, colorButton 7 | local datapoints = {} 8 | local currentPoint = nil 9 | 10 | local xoffLeft = 20 --/* histogram margins */ 11 | local yoffTop = 20 12 | local xoffRight = 20 13 | local yoffBottom = 20 14 | local pointRadius = 5 15 | 16 | local function setSolidBrush(brush, color, alpha) 17 | local component, r,g,b 18 | 19 | r = bit.band(bit.rshift(color,16),0xFF)/255 20 | g = bit.band(bit.rshift(color,8),0xFF)/255 21 | b = bit.band(color, 0xFF)/255 22 | brush:Type(ui.DrawBrushTypeSolid) 23 | :Solid(r,g,b,alpha) 24 | end 25 | 26 | -- and some colors 27 | -- names and values from https:--msdn.microsoft.com/en-us/library/windows/desktop/dd370907%28v=vs.85%29.aspx 28 | local colorWhite = 0xFFFFFF 29 | local colorBlack = 0x000000 30 | local colorDodgerBlue = 0x1E90FF 31 | 32 | local function pointLocations(width, height) 33 | local xincr, yincr; 34 | local i, n; 35 | local xs,ys = {},{} 36 | 37 | xincr = width / 9; -- 10 - 1 to make the last point be at the end 38 | yincr = height / 100; 39 | 40 | for i = 1,10 do 41 | ---- get the value of the point 42 | n = datapoints[i]:Value() 43 | ---- because y=0 is the top but n=0 is the bottom, we need to flip 44 | n = 100 - n 45 | xs[i] = xincr * (i-1); 46 | ys[i] = yincr * n; 47 | end 48 | return xs,ys 49 | end 50 | 51 | local function constructGraph(width, height, extend) 52 | local xs,ys = pointLocations(width, height); 53 | local path = ui.DrawNewPath(ui.DrawFillModeWinding); 54 | 55 | path:NewFigure(xs[1], ys[1]); 56 | for i=1,10 do 57 | path:LineTo(xs[i], ys[i]); 58 | end 59 | path:LineTo(xs[10], ys[10]); 60 | 61 | if extend then 62 | path:LineTo(width, height); 63 | path:LineTo(0, height); 64 | path:CloseFigure(); 65 | end 66 | 67 | path:End(); 68 | return path; 69 | end 70 | 71 | local function graphSize(clientWidth, clientHeight) 72 | return clientWidth - xoffLeft - xoffRight, 73 | clientHeight - yoffTop - yoffBottom 74 | end 75 | 76 | local function handlerDraw(a, area, p) 77 | local path,brush,sp,m,graphWidth, graphHeight,graphR, graphG, graphB, graphA 78 | 79 | -- fill the area with white 80 | brush = ui.DrawNewBrush() 81 | setSolidBrush(brush, colorWhite, 1.0) 82 | path = ui.DrawNewPath(ui.DrawFillModeWinding); 83 | path:AddRectangle(0, 0, p.AreaWidth, p.AreaHeight):End(path); 84 | p.Context:Fill(path, brush); 85 | path:Free() 86 | 87 | -- figure out dimensions 88 | graphWidth, graphHeight = graphSize(p.AreaWidth, p.AreaHeight); 89 | 90 | -- clear sp to avoid passing garbage to uiDrawStroke() 91 | -- for example, we don't use dashing 92 | sp = ui.DrawNewStrokeParams(); 93 | 94 | -- make a stroke for both the axes and the histogram line 95 | sp:Cap(ui.DrawLineCapFlat) 96 | sp:Join(ui.DrawLineJoinMiter) 97 | sp:Thickness(2) 98 | sp:MiterLimit(ui.DrawDefaultMiterLimit) 99 | 100 | -- draw the axes 101 | brush = ui.DrawNewBrush() 102 | setSolidBrush(brush, colorBlack, 1.0) 103 | path = ui.DrawNewPath(ui.DrawFillModeWinding); 104 | path:NewFigure(xoffLeft, yoffTop) 105 | :LineTo(xoffLeft, yoffTop + graphHeight) 106 | :LineTo(xoffLeft + graphWidth, yoffTop + graphHeight) 107 | :End() 108 | p.Context:Stroke(path, brush, sp); 109 | path:Free() 110 | 111 | -- now transform the coordinate space so (0, 0) is the top-left corner of the graph 112 | 113 | m = ui.DrawNewMatrix() 114 | m:SetIdentity():Translate(xoffLeft, yoffTop); 115 | p.Context:Transform(m); 116 | 117 | -- now get the color for the graph itself and set up the brush 118 | graphR, graphG, graphB, graphA = colorButton:Color(); 119 | brush:Type(ui.DrawBrushTypeSolid); 120 | -- we set brush->A below to different values for the fill and stroke 121 | 122 | -- now create the fill for the graph below the graph line 123 | 124 | path = constructGraph(graphWidth, graphHeight, true); 125 | brush:Solid(graphR,graphG,graphB,graphA / 2) 126 | p.Context:Fill(path, brush); 127 | path:Free() 128 | 129 | -- now draw the histogram line 130 | path = constructGraph(graphWidth, graphHeight, false); 131 | brush:Solid(graphR,graphG,graphB,graphA) 132 | p.Context:Stroke(path, brush, sp); 133 | path:Free() 134 | 135 | -- now draw the point being hovered over 136 | if (currentPoint) then 137 | local xs, ys = pointLocations(graphWidth, graphHeight); 138 | path = ui.DrawNewPath(ui.DrawFillModeWinding); 139 | path:NewFigureWithArc( 140 | xs[currentPoint], ys[currentPoint], 141 | pointRadius, 142 | 0, 6.23, -- TODO pi 143 | false); 144 | path:End() 145 | -- use the same brush as for the histogram lines 146 | p.Context:Fill(path, brush); 147 | path:Free() 148 | currentPoint = nil 149 | end 150 | end 151 | 152 | local function inPoint(x, y, xtest, ytest) 153 | -- TODO switch to using a matrix 154 | x = x - xoffLeft; 155 | y = y - yoffTop; 156 | return (x >= xtest - pointRadius) and 157 | (x <= xtest + pointRadius) and 158 | (y >= ytest - pointRadius) and 159 | (y <= ytest + pointRadius); 160 | end 161 | 162 | local function handlerMouseEvent(a, area, e) 163 | local graphWidth, graphHeight 164 | local xs,ys = {}, {} 165 | 166 | graphWidth, graphHeight = graphSize(e.AreaWidth, e.AreaHeight); 167 | xs, ys = pointLocations(graphWidth, graphHeight); 168 | for i=1,10 do 169 | if (inPoint(e.X, e.Y, xs[i], ys[i])) then 170 | currentPoint = i 171 | break; 172 | end 173 | end 174 | 175 | -- TODO only redraw the relevant area 176 | histogram:QueueRedrawAll(); 177 | end 178 | 179 | local function handlerMouseCrossed(ah, a, left) 180 | -- do nothing 181 | end 182 | 183 | local function handlerDragBroken(ah, a) 184 | -- do nothing 185 | end 186 | 187 | local function handlerKeyEvent(ah, a, e) 188 | -- reject all keys 189 | return 0; 190 | end 191 | 192 | local function onDatapointChanged(s, data) 193 | histogram:QueueRedrawAll(); 194 | end 195 | 196 | local function onColorChanged(b) 197 | histogram:QueueRedrawAll(); 198 | end 199 | 200 | local function onClosing(w) 201 | ui.Quit() 202 | return 1 203 | end 204 | 205 | local function shouldQuit() 206 | ui.ControlDestroy(mainwin) 207 | return true 208 | end 209 | 210 | local function uiMain() 211 | local ret,err = ui.Init(); 212 | if (not ret) then 213 | io.stderr:write(string.format("error initializing libui: %s", err)); 214 | return 1; 215 | end 216 | 217 | local hbox,vbox,brush; 218 | 219 | handler = ui.DrawNewAreaHandler( 220 | handlerDraw, 221 | handlerMouseEvent, 222 | handlerMouseCrossed, 223 | handlerDragBroken, 224 | handlerKeyEvent) 225 | 226 | ui.OnShouldQuit(shouldQuit); 227 | 228 | mainwin = ui.NewWindow("libui Histogram Example", 640, 480, true) 229 | :Margined(true) 230 | :OnClosing(onClosing); 231 | 232 | hbox = ui.NewHorizontalBox():Padded(true) 233 | mainwin:SetChild(hbox) 234 | 235 | vbox = ui.NewVerticalBox():Padded(true) 236 | hbox:Append(vbox,false) 237 | 238 | math.randomseed(os.time()) 239 | for i=1,10 do 240 | datapoints[i] = ui.NewSpinbox(0, 100) 241 | :Value(math.random(0,100)) 242 | :OnChanged(onDatapointChanged) 243 | vbox:Append(datapoints[i]) 244 | end 245 | 246 | colorButton = ui.NewColorButton() 247 | ---- TODO inline these 248 | brush = ui.DrawNewBrush() 249 | setSolidBrush(brush, colorDodgerBlue, 1.0) 250 | colorButton:OnChanged(onColorChanged):Color(brush:Solid()) 251 | vbox:Append(colorButton) 252 | 253 | histogram = ui.NewArea(handler) 254 | hbox:Append(histogram, true); 255 | mainwin:Show() 256 | ui.Main() 257 | ui.Uninit() 258 | 259 | return 0 260 | end 261 | 262 | uiMain() 263 | -------------------------------------------------------------------------------- /examples/multithread.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | 3 | local ui = require "lui" 4 | local _, uv = pcall(require, 'luv') 5 | if not _ then print('not support thread here') end 6 | 7 | local e 8 | 9 | local timeThread; 10 | 11 | local function threadproc() 12 | local uv = require 'luv' 13 | local ui = require 'lui' 14 | 15 | local function sayTime(time) 16 | print(time) 17 | end 18 | 19 | for i = 1, 3 do 20 | uv.sleep(1000); 21 | local t = os.date() 22 | ui.QueueMain(sayTime, t) 23 | end 24 | end 25 | 26 | local function onClosing(w, data) 27 | if timeThread then timeThread:join() end 28 | ui.Quit() 29 | return true 30 | end 31 | 32 | local function saySomething(b, data) 33 | e:Append("Saying something\n"); 34 | end 35 | 36 | function uiMain(void) 37 | local w, b, btn 38 | local ret, err = ui.Init() 39 | if not ret then error(err) end 40 | 41 | b = ui.NewVerticalBox():Padded(true) 42 | w = ui.NewWindow("Hello", 320, 240, false):Margined(true):SetChild(b) 43 | 44 | e = ui.NewMultilineEntry():ReadOnly(true) 45 | 46 | btn = ui.NewButton("Say Something"):OnClicked(saySomething) 47 | b:Append(btn, false):Append(e, true) 48 | w:OnClosing(onClosing):Show() 49 | timeThread = uv.new_thread(threadproc); 50 | ui.Main() 51 | ui.Uninit() 52 | end 53 | 54 | uiMain() 55 | -------------------------------------------------------------------------------- /examples/timer.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | 3 | local ui = require "lui" 4 | local mle = nil 5 | 6 | local function sayTime() 7 | local s = os.date() 8 | mle:Append(s..'\n') 9 | return false 10 | end 11 | 12 | local function onClosing(w, data) 13 | ui.Quit() 14 | return true 15 | end 16 | 17 | local function saySomething(b,data) 18 | mle:Append("Saying something\n"); 19 | end 20 | 21 | function uiMain(void) 22 | local w,b,btn 23 | local ret, err = ui.Init() 24 | if not ret then 25 | error(err) 26 | end 27 | 28 | b = ui.NewVerticalBox():Padded(true) 29 | w = ui.NewWindow("Hello", 320, 240, false) 30 | :Margined(true) 31 | :SetChild(b) 32 | 33 | mle = ui.NewMultilineEntry():ReadOnly(true) 34 | 35 | btn = ui.NewButton("Say Something"):OnClicked(saySomething) 36 | b:Append(btn,false) 37 | :Append(mle,true) 38 | w:OnClosing(onClosing):Show() 39 | ui.Timer(1000, sayTime) 40 | ui.Main() 41 | ui.Uninit() 42 | end 43 | 44 | uiMain() 45 | -------------------------------------------------------------------------------- /src/enum.c: -------------------------------------------------------------------------------- 1 | static void l_REG_UI_ENUM(lua_State *L, int idx) 2 | { 3 | lua_pushnumber(L, uiDrawDefaultMiterLimit); 4 | lua_setfield(L, -2, "DrawDefaultMiterLimit"); 5 | 6 | #define REG_UI_ENUM(x) \ 7 | lua_pushstring(L, #x); \ 8 | lua_pushinteger(L, ui##x); \ 9 | lua_rawset(L, idx) 10 | 11 | REG_UI_ENUM(ForEachContinue); 12 | REG_UI_ENUM(ForEachStop); 13 | 14 | REG_UI_ENUM(WindowResizeEdgeLeft); 15 | REG_UI_ENUM(WindowResizeEdgeTop); 16 | REG_UI_ENUM(WindowResizeEdgeRight); 17 | REG_UI_ENUM(WindowResizeEdgeBottom); 18 | REG_UI_ENUM(WindowResizeEdgeTopLeft); 19 | REG_UI_ENUM(WindowResizeEdgeTopRight); 20 | REG_UI_ENUM(WindowResizeEdgeBottomLeft); 21 | REG_UI_ENUM(WindowResizeEdgeBottomRight); 22 | 23 | REG_UI_ENUM(DrawBrushTypeSolid); 24 | REG_UI_ENUM(DrawBrushTypeLinearGradient); 25 | REG_UI_ENUM(DrawBrushTypeRadialGradient); 26 | REG_UI_ENUM(DrawBrushTypeImage); 27 | 28 | REG_UI_ENUM(DrawLineCapFlat); 29 | REG_UI_ENUM(DrawLineCapRound); 30 | REG_UI_ENUM(DrawLineCapSquare); 31 | 32 | REG_UI_ENUM(DrawLineJoinMiter); 33 | REG_UI_ENUM(DrawLineJoinRound); 34 | REG_UI_ENUM(DrawLineJoinBevel); 35 | 36 | REG_UI_ENUM(DrawFillModeWinding); 37 | REG_UI_ENUM(DrawFillModeAlternate); 38 | 39 | REG_UI_ENUM(AttributeTypeFamily); 40 | REG_UI_ENUM(AttributeTypeSize); 41 | REG_UI_ENUM(AttributeTypeWeight); 42 | REG_UI_ENUM(AttributeTypeItalic); 43 | REG_UI_ENUM(AttributeTypeStretch); 44 | REG_UI_ENUM(AttributeTypeColor); 45 | REG_UI_ENUM(AttributeTypeBackground); 46 | REG_UI_ENUM(AttributeTypeUnderline); 47 | REG_UI_ENUM(AttributeTypeUnderlineColor); 48 | REG_UI_ENUM(AttributeTypeFeatures); 49 | 50 | REG_UI_ENUM(TextWeightMinimum); 51 | REG_UI_ENUM(TextWeightThin); 52 | REG_UI_ENUM(TextWeightUltraLight); 53 | REG_UI_ENUM(TextWeightLight); 54 | REG_UI_ENUM(TextWeightBook); 55 | REG_UI_ENUM(TextWeightNormal); 56 | REG_UI_ENUM(TextWeightMedium); 57 | REG_UI_ENUM(TextWeightSemiBold); 58 | REG_UI_ENUM(TextWeightBold); 59 | REG_UI_ENUM(TextWeightUltraBold); 60 | REG_UI_ENUM(TextWeightHeavy); 61 | REG_UI_ENUM(TextWeightUltraHeavy); 62 | REG_UI_ENUM(TextWeightMaximum); 63 | 64 | REG_UI_ENUM(TextItalicNormal); 65 | REG_UI_ENUM(TextItalicOblique); 66 | REG_UI_ENUM(TextItalicItalic); 67 | 68 | REG_UI_ENUM(TextStretchUltraCondensed); 69 | REG_UI_ENUM(TextStretchExtraCondensed); 70 | REG_UI_ENUM(TextStretchCondensed); 71 | REG_UI_ENUM(TextStretchSemiCondensed); 72 | REG_UI_ENUM(TextStretchNormal); 73 | REG_UI_ENUM(TextStretchSemiExpanded); 74 | REG_UI_ENUM(TextStretchExpanded); 75 | REG_UI_ENUM(TextStretchExtraExpanded); 76 | REG_UI_ENUM(TextStretchUltraExpanded); 77 | 78 | REG_UI_ENUM(UnderlineNone); 79 | REG_UI_ENUM(UnderlineSingle); 80 | REG_UI_ENUM(UnderlineDouble); 81 | REG_UI_ENUM(UnderlineSuggestion); 82 | 83 | REG_UI_ENUM(UnderlineColorCustom); 84 | REG_UI_ENUM(UnderlineColorSpelling); 85 | REG_UI_ENUM(UnderlineColorGrammar); 86 | REG_UI_ENUM(UnderlineColorAuxiliary); // for instance); the color used by smart replacements on macOS or in Microsoft Office 87 | 88 | REG_UI_ENUM(DrawTextAlignLeft); 89 | REG_UI_ENUM(DrawTextAlignCenter); 90 | REG_UI_ENUM(DrawTextAlignRight); 91 | 92 | REG_UI_ENUM(ModifierCtrl); 93 | REG_UI_ENUM(ModifierAlt); 94 | REG_UI_ENUM(ModifierShift); 95 | REG_UI_ENUM(ModifierSuper); 96 | 97 | REG_UI_ENUM(ExtKeyEscape); 98 | REG_UI_ENUM(ExtKeyInsert); // eqREG_UI_ENUM(valent to "Help" on Apple keyboards 99 | REG_UI_ENUM(ExtKeyDelete); 100 | REG_UI_ENUM(ExtKeyHome); 101 | REG_UI_ENUM(ExtKeyEnd); 102 | REG_UI_ENUM(ExtKeyPageUp); 103 | REG_UI_ENUM(ExtKeyPageDown); 104 | REG_UI_ENUM(ExtKeyUp); 105 | REG_UI_ENUM(ExtKeyDown); 106 | REG_UI_ENUM(ExtKeyLeft); 107 | REG_UI_ENUM(ExtKeyRight); 108 | REG_UI_ENUM(ExtKeyF1); // F1..F12 are guaranteed to be consecutive 109 | REG_UI_ENUM(ExtKeyF2); 110 | REG_UI_ENUM(ExtKeyF3); 111 | REG_UI_ENUM(ExtKeyF4); 112 | REG_UI_ENUM(ExtKeyF5); 113 | REG_UI_ENUM(ExtKeyF6); 114 | REG_UI_ENUM(ExtKeyF7); 115 | REG_UI_ENUM(ExtKeyF8); 116 | REG_UI_ENUM(ExtKeyF9); 117 | REG_UI_ENUM(ExtKeyF10); 118 | REG_UI_ENUM(ExtKeyF11); 119 | REG_UI_ENUM(ExtKeyF12); 120 | REG_UI_ENUM(ExtKeyN0); // numpad keys; independent of Num Lock state 121 | REG_UI_ENUM(ExtKeyN1); // N0..N9 are guaranteed to be consecutive 122 | REG_UI_ENUM(ExtKeyN2); 123 | REG_UI_ENUM(ExtKeyN3); 124 | REG_UI_ENUM(ExtKeyN4); 125 | REG_UI_ENUM(ExtKeyN5); 126 | REG_UI_ENUM(ExtKeyN6); 127 | REG_UI_ENUM(ExtKeyN7); 128 | REG_UI_ENUM(ExtKeyN8); 129 | REG_UI_ENUM(ExtKeyN9); 130 | REG_UI_ENUM(ExtKeyNDot); 131 | REG_UI_ENUM(ExtKeyNEnter); 132 | REG_UI_ENUM(ExtKeyNAdd); 133 | REG_UI_ENUM(ExtKeyNSubtract); 134 | REG_UI_ENUM(ExtKeyNMultiply); 135 | REG_UI_ENUM(ExtKeyNDivide); 136 | 137 | REG_UI_ENUM(AlignFill); 138 | REG_UI_ENUM(AlignStart); 139 | REG_UI_ENUM(AlignCenter); 140 | REG_UI_ENUM(AlignEnd); 141 | 142 | REG_UI_ENUM(AtLeading); 143 | REG_UI_ENUM(AtTop); 144 | REG_UI_ENUM(AtTrailing); 145 | REG_UI_ENUM(AtBottom); 146 | 147 | REG_UI_ENUM(TableValueTypeString); 148 | REG_UI_ENUM(TableValueTypeImage); 149 | REG_UI_ENUM(TableValueTypeInt); 150 | REG_UI_ENUM(TableValueTypeColor); 151 | 152 | REG_UI_ENUM(TableModelColumnNeverEditable); 153 | REG_UI_ENUM(TableModelColumnAlwaysEditable); 154 | 155 | } 156 | -------------------------------------------------------------------------------- /src/larea.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewArea(lua_State *L) 2 | { 3 | uiAreaHandler *ah = CHECK_USER_OBJECT(1, AreaHandler); 4 | uiArea *a = NULL; 5 | if (lua_gettop(L) > 3) 6 | { 7 | a = uiNewScrollingArea(ah, luaL_checkinteger(L, 2), luaL_checkinteger(L, 3)); 8 | } 9 | else { 10 | a = uiNewArea(ah); 11 | } 12 | UI_CREATE_OBJECT(Area, a); 13 | lua_pushlightuserdata(L, a); 14 | lua_pushvalue(L, 1); 15 | lua_settable(L, LUA_REGISTRYINDEX); 16 | return 1; 17 | } 18 | 19 | static int l_uiAreaSetSize(lua_State *L) 20 | { 21 | uiAreaSetSize(UI_CHECK_OBJECT(1, Area), luaL_checkinteger(L, 2), luaL_checkinteger(L, 3)); 22 | UI_RETURN_SELF; 23 | } 24 | 25 | static int l_uiAreaQueueRedrawAll(lua_State *L) 26 | { 27 | uiAreaQueueRedrawAll(UI_CHECK_OBJECT(1, Area)); 28 | UI_RETURN_SELF; 29 | } 30 | 31 | static int l_uiAreaScrollTo(lua_State *L) 32 | { 33 | uiAreaScrollTo(UI_CHECK_OBJECT(1, Area), 34 | luaL_checknumber(L, 2), 35 | luaL_checknumber(L, 3), 36 | luaL_checknumber(L, 4), 37 | luaL_checknumber(L, 5)); 38 | UI_RETURN_SELF; 39 | } 40 | 41 | static int l_uiAreaBeginUserWindowMove(lua_State *L) 42 | { 43 | uiAreaBeginUserWindowMove(UI_CHECK_OBJECT(1, Area)); 44 | UI_RETURN_SELF; 45 | } 46 | 47 | static int l_uiAreaBeginUserWindowResize(lua_State *L) 48 | { 49 | uiAreaBeginUserWindowResize(UI_CHECK_OBJECT(1, Area), luaL_checkinteger(L, 2)); 50 | UI_RETURN_SELF; 51 | } 52 | 53 | static struct luaL_Reg meta_Area[] = 54 | { 55 | { "SetSize", l_uiAreaSetSize }, 56 | { "QueueRedrawAll", l_uiAreaQueueRedrawAll }, 57 | { "ScrollTo", l_uiAreaScrollTo }, 58 | { "BeginUserWindowMove", l_uiAreaBeginUserWindowMove }, 59 | { "BeginUserWindowResize", l_uiAreaBeginUserWindowResize }, 60 | 61 | CONTROL_COMMON_METAFIELD 62 | { NULL, NULL} 63 | }; 64 | -------------------------------------------------------------------------------- /src/lattribute.c: -------------------------------------------------------------------------------- 1 | // uiOpenTypeFeaturesForEachFunc is the type of the function 2 | // invoked by uiOpenTypeFeaturesForEach() for every OpenType 3 | // feature in otf. Refer to that function's documentation for more 4 | // details. 5 | 6 | static int l_uiNewOpenTypeFeatures(lua_State *L) 7 | { 8 | uiOpenTypeFeatures *f = uiNewOpenTypeFeatures(); 9 | CREATE_USER_OBJECT(OpenTypeFeatures, f); 10 | return 1; 11 | } 12 | 13 | static int l_uiFreeOpenTypeFeatures(lua_State *L) 14 | { 15 | uiOpenTypeFeatures *f = CHECK_USER_OBJECT(1, OpenTypeFeatures); 16 | uiFreeOpenTypeFeatures(f); 17 | return 0; 18 | } 19 | 20 | static int l_uiOpenTypeFeaturesClone(lua_State *L) 21 | { 22 | uiOpenTypeFeatures *f = CHECK_USER_OBJECT(1, OpenTypeFeatures); 23 | uiOpenTypeFeatures *a = uiOpenTypeFeaturesClone(f); 24 | CREATE_USER_OBJECT(OpenTypeFeatures, a); 25 | return 1; 26 | } 27 | 28 | static int l_uiOpenTypeFeaturesAdd(lua_State *L) 29 | { 30 | uiOpenTypeFeatures *f = CHECK_USER_OBJECT(1, OpenTypeFeatures); 31 | char a = (char)luaL_checkinteger(L, 2); 32 | char b = (char)luaL_checkinteger(L, 3); 33 | char c = (char)luaL_checkinteger(L, 4); 34 | char d = (char)luaL_checkinteger(L, 5); 35 | uint32_t value = luaL_checkinteger(L, 6); 36 | uiOpenTypeFeaturesAdd(f, a, b, c, d, value); 37 | UI_RETURN_SELF; 38 | } 39 | 40 | static int l_uiOpenTypeFeaturesRemove(lua_State *L) 41 | { 42 | uiOpenTypeFeatures *f = CHECK_USER_OBJECT(1, OpenTypeFeatures); 43 | char a = (char)luaL_checkinteger(L, 2); 44 | char b = (char)luaL_checkinteger(L, 3); 45 | char c = (char)luaL_checkinteger(L, 4); 46 | char d = (char)luaL_checkinteger(L, 5); 47 | uiOpenTypeFeaturesRemove(f, a, b, c, d); 48 | UI_RETURN_SELF; 49 | } 50 | 51 | static int l_uiOpenTypeFeaturesGet(lua_State *L) 52 | { 53 | uiOpenTypeFeatures *f = CHECK_USER_OBJECT(1, OpenTypeFeatures); 54 | char a = (char)luaL_checkinteger(L, 2); 55 | char b = (char)luaL_checkinteger(L, 3); 56 | char c = (char)luaL_checkinteger(L, 4); 57 | char d = (char)luaL_checkinteger(L, 5); 58 | uint32_t value = 0; 59 | uiOpenTypeFeaturesGet(f, a, b, c, d, &value); 60 | return 0; 61 | } 62 | 63 | static int l_uiOpenTypeFeaturesForEach(lua_State *L) 64 | { 65 | (void)L; 66 | //_UI_EXTERN void uiOpenTypeFeaturesForEach(const uiOpenTypeFeatures *otf, uiOpenTypeFeaturesForEachFunc f, void *data); 67 | return 0; 68 | } 69 | 70 | static struct luaL_Reg meta_OpenTypeFeatures[] = 71 | { 72 | { "__gc", l_uiFreeOpenTypeFeatures }, 73 | { "Free", l_uiFreeOpenTypeFeatures }, 74 | { "Clone", l_uiOpenTypeFeaturesClone }, 75 | 76 | { "Add", l_uiOpenTypeFeaturesAdd }, 77 | { "Remove", l_uiOpenTypeFeaturesRemove }, 78 | { "Get", l_uiOpenTypeFeaturesGet }, 79 | { "ForEach", l_uiOpenTypeFeaturesForEach }, 80 | 81 | { NULL, NULL } 82 | }; 83 | 84 | static int l_uiFreeAttribute(lua_State *L) 85 | { 86 | uiAttribute* attr = CHECK_USER_OBJECT(1, Attribute); 87 | uiFreeAttribute(attr); 88 | return 0; 89 | } 90 | 91 | static int l_uiAttributeGetType(lua_State *L) 92 | { 93 | uiAttribute* attr = CHECK_USER_OBJECT(1, Attribute); 94 | lua_pushinteger(L, uiAttributeGetType(attr)); 95 | return 1; 96 | } 97 | 98 | static int l_uiAttributeFamily(lua_State *L) 99 | { 100 | uiAttribute* attr = CHECK_USER_OBJECT(1, Attribute); 101 | lua_pushstring(L, uiAttributeFamily(attr)); 102 | return 1; 103 | } 104 | 105 | static int l_uiAttributeSize(lua_State *L) 106 | { 107 | uiAttribute* attr = CHECK_USER_OBJECT(1, Attribute); 108 | lua_pushnumber(L, uiAttributeSize(attr)); 109 | return 1; 110 | } 111 | 112 | static int l_uiAttributeWeight(lua_State *L) 113 | { 114 | uiAttribute* attr = CHECK_USER_OBJECT(1, Attribute); 115 | lua_pushinteger(L, uiAttributeWeight(attr)); 116 | return 1; 117 | } 118 | 119 | static int l_uiAttributeItalic(lua_State *L) 120 | { 121 | uiAttribute* attr = CHECK_USER_OBJECT(1, Attribute); 122 | lua_pushinteger(L, uiAttributeItalic(attr)); 123 | return 1; 124 | } 125 | 126 | static int l_uiAttributeStretch(lua_State *L) 127 | { 128 | uiAttribute* attr = CHECK_USER_OBJECT(1, Attribute); 129 | lua_pushinteger(L, uiAttributeStretch(attr)); 130 | return 1; 131 | } 132 | 133 | static int l_uiAttributeColor(lua_State *L) 134 | { 135 | uiAttribute* attr = CHECK_USER_OBJECT(1, Attribute); 136 | double r, g, b, a; 137 | uiAttributeColor(attr, &r, &g, &b, &a); 138 | lua_pushnumber(L, r); 139 | lua_pushnumber(L, g); 140 | lua_pushnumber(L, b); 141 | lua_pushnumber(L, a); 142 | return 4; 143 | } 144 | 145 | 146 | static int l_uiAttributeUnderlineColor(lua_State *L) 147 | { 148 | uiAttribute* attr = CHECK_USER_OBJECT(1, Attribute); 149 | uiUnderlineColor u; 150 | double r, g, b, a; 151 | uiAttributeUnderlineColor(attr, &u, &r, &g, &b, &a); 152 | lua_pushnumber(L, u); 153 | lua_pushnumber(L, r); 154 | lua_pushnumber(L, g); 155 | lua_pushnumber(L, b); 156 | lua_pushnumber(L, a); 157 | return 5; 158 | } 159 | static int l_uiAttributeUnderline(lua_State *L) 160 | { 161 | uiAttribute* attr = CHECK_USER_OBJECT(1, Attribute); 162 | lua_pushinteger(L, uiAttributeUnderline(attr)); 163 | return 1; 164 | } 165 | 166 | static int l_uiAttributeFeatures(lua_State *L) 167 | { 168 | uiAttribute* attr = CHECK_USER_OBJECT(1, Attribute); 169 | const uiOpenTypeFeatures* features = uiAttributeFeatures(attr); 170 | CREATE_USER_OBJECT(OpenTypeFeatures, (uiOpenTypeFeatures*)features); 171 | return 1; 172 | } 173 | 174 | /* uiFontButtonDescriptor */ 175 | static int l_uiAttribute2table(lua_State *L, const uiAttribute *atr) 176 | { 177 | lua_newtable(L); 178 | lua_pushinteger(L, uiAttributeGetType(atr)); 179 | lua_setfield(L, -2, "type"); 180 | lua_pushstring(L, uiAttributeFamily(atr)); 181 | lua_setfield(L, -2, "family"); 182 | lua_pushnumber(L, uiAttributeSize(atr)); 183 | lua_setfield(L, -2, "size"); 184 | lua_pushinteger(L, uiAttributeWeight(atr)); 185 | lua_setfield(L, -2, "weight"); 186 | lua_pushinteger(L, uiAttributeItalic(atr)); 187 | lua_setfield(L, -2, "italic"); 188 | lua_pushinteger(L, uiAttributeStretch(atr)); 189 | lua_setfield(L, -2, "stretch"); 190 | lua_pushinteger(L, uiAttributeUnderline(atr)); 191 | lua_setfield(L, -2, "underline"); 192 | 193 | //color 194 | //underlinecolor 195 | return 1; 196 | } 197 | 198 | static int l_uiAttribute2tableInfo(lua_State *L) 199 | { 200 | uiAttribute* attr = CHECK_USER_OBJECT(1, Attribute); 201 | l_uiAttribute2table(L, attr); 202 | return 1; 203 | } 204 | 205 | 206 | static struct luaL_Reg meta_Attribute[] = 207 | { 208 | { "__gc", l_uiFreeAttribute }, 209 | { "Free", l_uiFreeAttribute }, 210 | { "Type", l_uiAttributeGetType }, 211 | { "Family", l_uiAttributeFamily }, 212 | { "Size", l_uiAttributeSize }, 213 | { "Weight", l_uiAttributeWeight }, 214 | { "Italic", l_uiAttributeItalic }, 215 | { "Stretch", l_uiAttributeStretch }, 216 | { "Color", l_uiAttributeColor }, 217 | { 218 | "UnderlineColor", 219 | l_uiAttributeUnderlineColor 220 | }, 221 | { "Underline", l_uiAttributeUnderline }, 222 | { "Features", l_uiAttributeFeatures }, 223 | 224 | { "info", l_uiAttribute2tableInfo}, 225 | { NULL, NULL } 226 | }; 227 | 228 | static int l_uiNewAttribute(lua_State *L) 229 | { 230 | uiAttribute *attr = NULL; 231 | const char* item = luaL_checkstring(L, 1); 232 | if (strcmp(item, "family") == 0) 233 | { 234 | attr = uiNewFamilyAttribute(luaL_checkstring(L, 2)); 235 | } 236 | else if (strcmp(item, "size") == 0) 237 | { 238 | attr = uiNewSizeAttribute(luaL_checknumber(L, 2)); 239 | } 240 | else if (strcmp(item, "weight") == 0) 241 | { 242 | attr = uiNewWeightAttribute(luaL_checkinteger(L, 2)); 243 | } 244 | else if (strcmp(item, "italic") == 0) 245 | { 246 | attr = uiNewItalicAttribute(luaL_checkinteger(L, 2)); 247 | } 248 | else if (strcmp(item, "stretch") == 0) 249 | { 250 | attr = uiNewStretchAttribute(luaL_checkinteger(L, 2)); 251 | } 252 | else if (strcmp(item, "color") == 0) 253 | { 254 | attr = uiNewColorAttribute(luaL_checknumber(L, 2), 255 | luaL_checknumber(L, 3), 256 | luaL_checknumber(L, 4), 257 | luaL_checknumber(L, 5)); 258 | } 259 | else if (strcmp(item, "background") == 0) 260 | { 261 | attr = uiNewBackgroundAttribute(luaL_checknumber(L, 2), 262 | luaL_checknumber(L, 3), 263 | luaL_checknumber(L, 4), 264 | luaL_checknumber(L, 5)); 265 | } 266 | else if (strcmp(item, "underline") == 0) 267 | { 268 | attr = uiNewUnderlineAttribute(luaL_checkinteger(L, 2)); 269 | } 270 | else if (strcmp(item, "underlinecolor") == 0) 271 | { 272 | attr = uiNewUnderlineColorAttribute(luaL_checkinteger(L, 2), 273 | luaL_checknumber(L, 3), 274 | luaL_checknumber(L, 4), 275 | luaL_checknumber(L, 5), 276 | luaL_checknumber(L, 6)); 277 | } 278 | else if (strcmp(item, "features") == 0) 279 | { 280 | const uiOpenTypeFeatures *features = CHECK_USER_OBJECT(2, OpenTypeFeatures); 281 | attr = uiNewFeaturesAttribute(features); 282 | } 283 | else 284 | luaL_argerror(L, 1, "not support"); 285 | 286 | CREATE_USER_OBJECT(Attribute, attr); 287 | return 1; 288 | } 289 | -------------------------------------------------------------------------------- /src/lattributedstr.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewAttributedString(lua_State *L) 2 | { 3 | const char *initialString = luaL_checkstring(L, 1); 4 | uiAttributedString *s = uiNewAttributedString(initialString); 5 | CREATE_USER_OBJECT(AttributedString, s); 6 | return 1; 7 | } 8 | 9 | static int l_uiFreeAttributedString(lua_State *L) 10 | { 11 | uiAttributedString *s = CHECK_USER_OBJECT(1, AttributedString); 12 | uiFreeAttributedString(s); 13 | return 0; 14 | } 15 | 16 | static int l_uiAttributedStringString(lua_State *L) 17 | { 18 | uiAttributedString *s = CHECK_USER_OBJECT(1, AttributedString); 19 | int len = uiAttributedStringLen(s); 20 | lua_pushlstring(L, uiAttributedStringString(s), len); 21 | return 1; 22 | } 23 | 24 | static int l_uiAttributedStringLen(lua_State *L) 25 | { 26 | uiAttributedString *s = CHECK_USER_OBJECT(1, AttributedString); 27 | lua_pushinteger(L, uiAttributedStringLen(s)); 28 | return 1; 29 | } 30 | 31 | static int l_uiAttributedStringAppendUnattributed(lua_State *L) 32 | { 33 | uiAttributedString *s = CHECK_USER_OBJECT(1, AttributedString); 34 | uiAttributedStringAppendUnattributed(s, luaL_checkstring(L, 2)); 35 | UI_RETURN_SELF; 36 | } 37 | 38 | static int l_uiAttributedStringInsertAtUnattributed(lua_State *L) 39 | { 40 | uiAttributedString *s = CHECK_USER_OBJECT(1, AttributedString); 41 | uiAttributedStringInsertAtUnattributed(s, luaL_checkstring(L, 2), luaL_checkinteger(L, 3)); 42 | UI_RETURN_SELF; 43 | } 44 | 45 | static int l_uiAttributedStringDelete(lua_State *L) 46 | { 47 | uiAttributedString *s = CHECK_USER_OBJECT(1, AttributedString); 48 | uiAttributedStringDelete(s, luaL_checkinteger(L, 2), luaL_checkinteger(L, 3)); 49 | UI_RETURN_SELF; 50 | } 51 | 52 | static int l_uiAttributedStringSetAttribute(lua_State *L) 53 | { 54 | uiAttributedString *s = CHECK_USER_OBJECT(1, AttributedString); 55 | uiAttribute *a = CHECK_USER_OBJECT(2, Attribute); 56 | uiAttributedStringSetAttribute(s, a, luaL_checkinteger(L, 3), luaL_checkinteger(L, 4)); 57 | UI_RETURN_SELF; 58 | } 59 | 60 | static int l_uiAttributedStringNumGraphemes(lua_State *L) 61 | { 62 | uiAttributedString *s = CHECK_USER_OBJECT(1, AttributedString); 63 | size_t sz = uiAttributedStringNumGraphemes(s); 64 | lua_pushinteger(L, sz); 65 | return 1; 66 | } 67 | 68 | static int l_uiAttributedStringByteIndexToGrapheme(lua_State *L) 69 | { 70 | uiAttributedString *s = CHECK_USER_OBJECT(1, AttributedString); 71 | size_t sz = uiAttributedStringByteIndexToGrapheme(s, (size_t)luaL_checkinteger(L, 2)); 72 | lua_pushinteger(L, sz); 73 | return 1; 74 | } 75 | 76 | static int l_uiAttributedStringGraphemeToByteIndex(lua_State *L) 77 | { 78 | uiAttributedString *s = CHECK_USER_OBJECT(1, AttributedString); 79 | size_t sz = uiAttributedStringGraphemeToByteIndex(s, (size_t)luaL_checkinteger(L, 2)); 80 | lua_pushinteger(L, sz); 81 | return 1; 82 | } 83 | 84 | static int l_uiAttributedStringForEachAttribute(lua_State *L) 85 | { 86 | //uiAttributedString *s = CHECK_USER_OBJECT(1, AttributedString); 87 | //_UI_EXTERN void uiAttributedStringForEachAttribute(const uiAttributedString *s, uiAttributedStringForEachAttributeFunc f, void *data); 88 | //uiAttributedStringForEachAttribute(s, (size_t)luaL_checkinteger(L, 2)); 89 | //lua_pushinteger(L, sz); 90 | return 0; 91 | } 92 | 93 | static struct luaL_Reg meta_AttributedString[] = 94 | { 95 | { "__gc", l_uiFreeAttributedString }, 96 | { "__len", l_uiAttributedStringLen }, 97 | { "__tostring", l_uiAttributedStringString }, 98 | 99 | { "Free", l_uiFreeAttributedString }, 100 | { "String", l_uiAttributedStringString }, 101 | { "Len", l_uiAttributedStringLen }, 102 | { "AppendUnattributed", l_uiAttributedStringAppendUnattributed }, 103 | { "InsertAtUnattributed", l_uiAttributedStringInsertAtUnattributed}, 104 | { "Delete", l_uiAttributedStringDelete}, 105 | { "SetAttribute", l_uiAttributedStringSetAttribute}, 106 | { "NumGraphemes", l_uiAttributedStringNumGraphemes}, 107 | { "ByteIndexToGrapheme", l_uiAttributedStringByteIndexToGrapheme}, 108 | { "GraphemeToByteIndex", l_uiAttributedStringGraphemeToByteIndex}, 109 | { "ForEach", l_uiAttributedStringForEachAttribute}, 110 | 111 | { NULL, NULL } 112 | }; 113 | -------------------------------------------------------------------------------- /src/lbox.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewHorizontalBox(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(Box, uiNewHorizontalBox()); 4 | return 1; 5 | } 6 | 7 | static int l_uiNewVerticalBox(lua_State *L) 8 | { 9 | UI_CREATE_OBJECT(Box, uiNewVerticalBox()); 10 | return 1; 11 | } 12 | 13 | static int l_uiBoxAppend(lua_State *L) 14 | { 15 | int i; 16 | int stretchy = 0; 17 | int n = lua_gettop(L); 18 | uiBox *box = UI_CHECK_OBJECT(1, Box); 19 | uiControl *child = NULL; 20 | 21 | if (lua_isboolean(L, n)) 22 | { 23 | stretchy = lua_toboolean(L, n); 24 | n = n - 1; 25 | } 26 | 27 | for (i = 2; i <= n; i++) 28 | { 29 | child = UI_CHECK_OBJECT(i, Control); 30 | uiBoxAppend(box, child, stretchy); 31 | lua_getmetatable(L, 1); 32 | lua_pushvalue(L, i); 33 | luaL_ref(L, -2); 34 | } 35 | UI_RETURN_SELF; 36 | } 37 | 38 | static int l_uiBoxDelete(lua_State *L) 39 | { 40 | uiBoxDelete(UI_CHECK_OBJECT(1, Box), luaL_checkinteger(L, 2)); 41 | UI_RETURN_SELF; 42 | } 43 | 44 | static int l_uiBoxPadded(lua_State *L) 45 | { 46 | if (lua_isnone(L, 2)) 47 | { 48 | lua_pushboolean(L, uiBoxPadded(UI_CHECK_OBJECT(1, Box))); 49 | return 1; 50 | } 51 | uiBoxSetPadded(UI_CHECK_OBJECT(1, Box), luaL_checkboolean(L, 2)); 52 | UI_RETURN_SELF; 53 | } 54 | 55 | static struct luaL_Reg meta_Box[] = 56 | { 57 | { "Append", l_uiBoxAppend }, 58 | { "Delete", l_uiBoxDelete }, 59 | { "Padded", l_uiBoxPadded }, 60 | 61 | CONTROL_COMMON_METAFIELD 62 | { NULL, NULL } 63 | }; 64 | -------------------------------------------------------------------------------- /src/lbutton.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewButton(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(Button, uiNewButton(luaL_checkstring(L, 1))); 4 | return 1; 5 | } 6 | 7 | static int l_uiButtonText(lua_State *L) 8 | { 9 | if (lua_isnone(L, 2)) 10 | { 11 | char* text = uiButtonText(UI_CHECK_OBJECT(1, Button)); 12 | lua_pushstring(L, text); 13 | return 1; 14 | } 15 | uiButtonSetText(UI_CHECK_OBJECT(1, Button), luaL_checkstring(L, 2)); 16 | UI_RETURN_SELF; 17 | } 18 | 19 | static void on_button_clicked(uiButton *b, void *data) 20 | { 21 | callback(data, b, "clicked"); 22 | } 23 | 24 | static int l_uiButtonOnClicked(lua_State *L) 25 | { 26 | uiButtonOnClicked(UI_CHECK_OBJECT(1, Button), on_button_clicked, L); 27 | create_callback_data(L, 1, "clicked"); 28 | UI_RETURN_SELF; 29 | } 30 | 31 | static struct luaL_Reg meta_Button[] = 32 | { 33 | { "Text", l_uiButtonText }, 34 | { "OnClicked", l_uiButtonOnClicked }, 35 | 36 | CONTROL_COMMON_METAFIELD 37 | { NULL, NULL } 38 | }; 39 | -------------------------------------------------------------------------------- /src/lcheckbox.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewCheckbox(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(Checkbox, uiNewCheckbox(luaL_checkstring(L, 1))); 4 | return 1; 5 | } 6 | 7 | static int l_uiCheckboxText(lua_State *L) 8 | { 9 | if (lua_isnone(L, 2)) 10 | { 11 | lua_pushstring(L, uiCheckboxText(UI_CHECK_OBJECT(1, Checkbox))); 12 | return 1; 13 | } 14 | uiCheckboxSetText(UI_CHECK_OBJECT(1, Checkbox), luaL_checkstring(L, 2)); 15 | UI_RETURN_SELF; 16 | } 17 | 18 | static void on_checkbox_toggled(uiCheckbox *c, void *data) 19 | { 20 | callback(data, c, "toggled"); 21 | } 22 | 23 | static int l_uiCheckboxOnToggled(lua_State *L) 24 | { 25 | uiCheckboxOnToggled(UI_CHECK_OBJECT(1, Checkbox), on_checkbox_toggled, L); 26 | create_callback_data(L, 1, "toggled"); 27 | UI_RETURN_SELF; 28 | } 29 | 30 | static int l_uiCheckboxChecked(lua_State *L) 31 | { 32 | if (lua_isnone(L, 2)) 33 | { 34 | lua_pushboolean(L, uiCheckboxChecked(UI_CHECK_OBJECT(1, Checkbox))); 35 | return 1; 36 | } 37 | uiCheckboxSetChecked(UI_CHECK_OBJECT(1, Checkbox), luaL_checkboolean(L, 2)); 38 | UI_RETURN_SELF; 39 | } 40 | 41 | static struct luaL_Reg meta_Checkbox[] = 42 | { 43 | { "Text", l_uiCheckboxText }, 44 | { "OnToggled", l_uiCheckboxOnToggled }, 45 | { "Checked", l_uiCheckboxChecked }, 46 | 47 | CONTROL_COMMON_METAFIELD 48 | { NULL, NULL } 49 | }; 50 | -------------------------------------------------------------------------------- /src/lcolorbutton.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewColorButton(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(ColorButton, uiNewColorButton()); 4 | return 1; 5 | } 6 | 7 | static int l_uiColorButtonColor(lua_State *L) 8 | { 9 | double r, g, b, a; 10 | if (lua_isnone(L, 2)) 11 | { 12 | uiColorButtonColor(UI_CHECK_OBJECT(1, ColorButton), &r, &g, &b, &a); 13 | lua_pushnumber(L, r); 14 | lua_pushnumber(L, g); 15 | lua_pushnumber(L, b); 16 | lua_pushnumber(L, a); 17 | return 4; 18 | } 19 | uiColorButtonSetColor(UI_CHECK_OBJECT(1, ColorButton), 20 | luaL_checknumber(L, 2), 21 | luaL_checknumber(L, 3), 22 | luaL_checknumber(L, 4), 23 | luaL_checknumber(L, 5)); 24 | UI_RETURN_SELF; 25 | } 26 | 27 | static void on_colorbutton_changed(uiColorButton *b, void *data) 28 | { 29 | callback(data, b, "changed"); 30 | } 31 | 32 | static int l_uiColorButtonOnChanged(lua_State *L) 33 | { 34 | uiColorButtonOnChanged(UI_CHECK_OBJECT(1, ColorButton), on_colorbutton_changed, L); 35 | create_callback_data(L, 1, "changed"); 36 | UI_RETURN_SELF; 37 | } 38 | 39 | static struct luaL_Reg meta_ColorButton[] = 40 | { 41 | { "Color", l_uiColorButtonColor }, 42 | { "OnChanged", l_uiColorButtonOnChanged }, 43 | 44 | CONTROL_COMMON_METAFIELD 45 | { NULL, NULL } 46 | }; 47 | -------------------------------------------------------------------------------- /src/lcombobox.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewCombobox(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(Combobox, uiNewCombobox()); 4 | return 1; 5 | } 6 | 7 | static int l_uiComboboxAppend(lua_State *L) 8 | { 9 | int n = lua_gettop(L); 10 | int i; 11 | for (i = 2; i <= n; i++) 12 | { 13 | const char *text = luaL_checkstring(L, n); 14 | uiComboboxAppend(UI_CHECK_OBJECT(1, Combobox), text); 15 | } 16 | UI_RETURN_SELF; 17 | } 18 | 19 | static int l_uiComboboxSelected(lua_State *L) 20 | { 21 | if (lua_isnone(L, 2)) 22 | { 23 | lua_pushinteger(L, uiComboboxSelected(UI_CHECK_OBJECT(1, Combobox))); 24 | return 1; 25 | } 26 | uiComboboxSetSelected(UI_CHECK_OBJECT(1, Combobox), luaL_checkinteger(L, 2)); 27 | UI_RETURN_SELF; 28 | } 29 | 30 | static void on_combobox_selected(uiCombobox *c, void *data) 31 | { 32 | callback(data, c, "selected"); 33 | } 34 | 35 | static int l_uiComboboxOnSelected(lua_State *L) 36 | { 37 | uiComboboxOnSelected(UI_CHECK_OBJECT(1, Combobox), on_combobox_selected, L); 38 | create_callback_data(L, 1, "selected"); 39 | UI_RETURN_SELF; 40 | } 41 | 42 | static struct luaL_Reg meta_Combobox[] = 43 | { 44 | { "Append", l_uiComboboxAppend }, 45 | { "Selected", l_uiComboboxSelected }, 46 | { "OnSelected", l_uiComboboxOnSelected }, 47 | 48 | CONTROL_COMMON_METAFIELD 49 | { NULL, NULL } 50 | }; 51 | 52 | static int l_uiNewEditableCombobox(lua_State *L) 53 | { 54 | UI_CREATE_OBJECT(EditableCombobox, uiNewEditableCombobox()); 55 | return 1; 56 | } 57 | 58 | static int l_uiEditableComboboxAppend(lua_State *L) 59 | { 60 | int n = lua_gettop(L); 61 | int i; 62 | for (i = 2; i <= n; i++) 63 | { 64 | const char *text = luaL_checkstring(L, n); 65 | uiEditableComboboxAppend(UI_CHECK_OBJECT(1, EditableCombobox), text); 66 | } 67 | UI_RETURN_SELF; 68 | } 69 | 70 | static int l_uiEditableComboboxText(lua_State *L) 71 | { 72 | if (lua_isnone(L, 2)) 73 | { 74 | lua_pushstring(L, uiEditableComboboxText(UI_CHECK_OBJECT(1, EditableCombobox))); 75 | return 1; 76 | } 77 | uiEditableComboboxSetText(UI_CHECK_OBJECT(1, EditableCombobox), luaL_checkstring(L, 2)); 78 | UI_RETURN_SELF; 79 | } 80 | 81 | static void on_EditableCombobox_Changed(uiEditableCombobox *c, void *data) 82 | { 83 | callback(data, c, "changed"); 84 | } 85 | 86 | static int l_uiEditableComboboxOnChanged(lua_State *L) 87 | { 88 | uiEditableComboboxOnChanged(UI_CHECK_OBJECT(1, EditableCombobox), on_EditableCombobox_Changed, L); 89 | create_callback_data(L, 1, "changed"); 90 | UI_RETURN_SELF; 91 | } 92 | 93 | static struct luaL_Reg meta_EditableCombobox[] = 94 | { 95 | { "Append", l_uiEditableComboboxAppend }, 96 | { "Text", l_uiEditableComboboxText }, 97 | { "OnChanged", l_uiEditableComboboxOnChanged }, 98 | 99 | CONTROL_COMMON_METAFIELD 100 | { NULL, NULL } 101 | }; 102 | -------------------------------------------------------------------------------- /src/lcontrol.c: -------------------------------------------------------------------------------- 1 | static int l_uiControlDestroy(lua_State *L) 2 | { 3 | struct wrap *w = NULL; 4 | uiControl *c = NULL; 5 | 6 | if(auxiliar_getclassudata(L, "libui.Control", 1)) 7 | w = (struct wrap*)lua_touserdata(L, 1); 8 | else 9 | w = (struct wrap*)auxiliar_checkgroup(L, "libui.Control", 1); 10 | 11 | c = w->control; 12 | if(c!=NULL && w->ref) 13 | uiControlDestroy(c); 14 | w->control = NULL; 15 | 16 | lua_pushnil(L); 17 | lua_setmetatable(L, 1); 18 | return 0; 19 | } 20 | 21 | static uiControl* l_checkControl(lua_State *L, int i) 22 | { 23 | struct wrap *w = NULL; 24 | 25 | if(auxiliar_getclassudata(L, "libui.Control", i)) 26 | w = (struct wrap*)lua_touserdata(L, i); 27 | else 28 | w = (struct wrap*)auxiliar_checkgroup(L, "libui.Control", i); 29 | 30 | return w->control; 31 | } 32 | 33 | static int l_uiControlHandle(lua_State *L) 34 | { 35 | lua_pushinteger(L, uiControlHandle(l_checkControl(L, 1))); 36 | return 1; 37 | } 38 | 39 | static int l_uiControlParent(lua_State *L) 40 | { 41 | if (lua_isnone(L, 2)) 42 | { 43 | UI_CREATE_OBJECT(Control, uiControlParent(l_checkControl(L, 1))); 44 | return 1; 45 | } 46 | uiControlSetParent(l_checkControl(L, 1), l_checkControl(L, 2)); 47 | UI_RETURN_SELF; 48 | } 49 | 50 | static int l_uiControlToplevel(lua_State *L) 51 | { 52 | lua_pushinteger(L, uiControlToplevel(l_checkControl(L, 1))); 53 | return 1; 54 | } 55 | 56 | static int l_uiControlVisible(lua_State *L) 57 | { 58 | lua_pushboolean(L, uiControlVisible(l_checkControl(L, 1))); 59 | return 1; 60 | } 61 | 62 | static int l_uiControlShow(lua_State *L) 63 | { 64 | uiControlShow(l_checkControl(L, 1)); 65 | UI_RETURN_SELF; 66 | } 67 | 68 | static int l_uiControlHide(lua_State *L) 69 | { 70 | uiControlHide(l_checkControl(L, 1)); 71 | UI_RETURN_SELF; 72 | } 73 | 74 | static int l_uiControlEnabled(lua_State *L) 75 | { 76 | lua_pushboolean(L, uiControlEnabled(l_checkControl(L, 1))); 77 | return 1; 78 | } 79 | 80 | static int l_uiControlEnable(lua_State *L) 81 | { 82 | uiControlEnable(l_checkControl(L, 1)); 83 | UI_RETURN_SELF; 84 | } 85 | static int l_uiControlDisable(lua_State *L) 86 | { 87 | uiControlDisable(l_checkControl(L, 1)); 88 | UI_RETURN_SELF; 89 | } 90 | 91 | static int l_uiControlVerifySetParent(lua_State *L) 92 | { 93 | uiControlVerifySetParent(l_checkControl(L, 1), l_checkControl(L, 2)); 94 | UI_RETURN_SELF; 95 | } 96 | 97 | static int l_uiControlEnabledToUser(lua_State *L) 98 | { 99 | lua_pushboolean(L, uiControlEnabledToUser(l_checkControl(L, 1))); 100 | return 1; 101 | } 102 | 103 | #define CONTROL_COMMON_METAFIELD \ 104 | { "Destroy", l_uiControlDestroy }, \ 105 | { "Handle", l_uiControlHandle }, \ 106 | { "Parent", l_uiControlParent }, \ 107 | { "Toplevel", l_uiControlToplevel }, \ 108 | { "Visible", l_uiControlVisible }, \ 109 | { "Show", l_uiControlShow }, \ 110 | { "Hide", l_uiControlHide }, \ 111 | { "Enabled", l_uiControlEnabled }, \ 112 | { "Enable", l_uiControlEnable }, \ 113 | { "Disable", l_uiControlDisable }, \ 114 | { "EnabledToUser", l_uiControlEnabledToUser }, \ 115 | { "VerifySetParent", l_uiControlVerifySetParent }, 116 | 117 | static struct luaL_Reg meta_Control[] = 118 | { 119 | CONTROL_COMMON_METAFIELD 120 | 121 | {NULL, NULL} 122 | }; 123 | -------------------------------------------------------------------------------- /src/ldatetimerpicker.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewDateTimePicker(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(DateTimePicker, uiNewDateTimePicker()); 4 | return 1; 5 | } 6 | 7 | static int l_uiNewDatePicker(lua_State *L) 8 | { 9 | UI_CREATE_OBJECT(DateTimePicker, uiNewDatePicker()); 10 | return 1; 11 | } 12 | 13 | static int l_uiNewTimePicker(lua_State *L) 14 | { 15 | UI_CREATE_OBJECT(DateTimePicker, uiNewTimePicker()); 16 | return 1; 17 | } 18 | 19 | /* copy from lua source */ 20 | /* 21 | ** {====================================================== 22 | ** Time/Date operations 23 | ** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, 24 | ** wday=%w+1, yday=%j, isdst=? } 25 | ** ======================================================= 26 | */ 27 | 28 | static void setfield (lua_State *L, const char *key, int value) 29 | { 30 | lua_pushinteger(L, value); 31 | lua_setfield(L, -2, key); 32 | } 33 | 34 | static void setboolfield (lua_State *L, const char *key, int value) 35 | { 36 | if (value < 0) /* undefined? */ 37 | return; /* does not set field */ 38 | lua_pushboolean(L, value); 39 | lua_setfield(L, -2, key); 40 | } 41 | 42 | #include 43 | /* 44 | ** Set all fields from structure 'tm' in the table on top of the stack 45 | */ 46 | static void setallfields (lua_State *L, struct tm *stm) 47 | { 48 | setfield(L, "sec", stm->tm_sec); 49 | setfield(L, "min", stm->tm_min); 50 | setfield(L, "hour", stm->tm_hour); 51 | setfield(L, "day", stm->tm_mday); 52 | setfield(L, "month", stm->tm_mon + 1); 53 | setfield(L, "year", stm->tm_year + 1900); 54 | // setfield(L, "wday", stm->tm_wday + 1); 55 | // setfield(L, "yday", stm->tm_yday + 1); 56 | if(stm->tm_isdst!=-1) 57 | setboolfield(L, "isdst", stm->tm_isdst); 58 | } 59 | 60 | 61 | static int getboolfield (lua_State *L, const char *key) 62 | { 63 | int res; 64 | res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1); 65 | lua_pop(L, 1); 66 | return res; 67 | } 68 | 69 | 70 | /* maximum value for date fields (to avoid arithmetic overflows with 'int') */ 71 | #if !defined(L_MAXDATEFIELD) 72 | #define L_MAXDATEFIELD (INT_MAX / 2) 73 | #endif 74 | 75 | static int getfield (lua_State *L, const char *key, int d, int delta) 76 | { 77 | int isnum; 78 | int t = lua_getfield(L, -1, key); /* get field and its type */ 79 | lua_Integer res = lua_tointegerx(L, -1, &isnum); 80 | if (!isnum) /* field is not an integer? */ 81 | { 82 | if (t != LUA_TNIL) /* some other value? */ 83 | return luaL_error(L, "field '%s' is not an integer", key); 84 | else if (d < 0) /* absent field; no default? */ 85 | return luaL_error(L, "field '%s' missing in date table", key); 86 | res = d; 87 | } 88 | else 89 | { 90 | if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD)) 91 | return luaL_error(L, "field '%s' is out-of-bound", key); 92 | res -= delta; 93 | } 94 | lua_pop(L, 1); 95 | return (int)res; 96 | } 97 | 98 | // TODO document that tm_wday and tm_yday are undefined, and tm_isdst should be -1 99 | static int l_uiDateTimePickerTime(lua_State *L) 100 | { 101 | uiDateTimePicker *picker = UI_CHECK_OBJECT(1, DateTimePicker); 102 | struct tm time = {0}; 103 | uiDateTimePickerTime(picker, &time); 104 | lua_createtable(L, 0, 9); 105 | setallfields(L, &time); 106 | return 1; 107 | } 108 | 109 | static int l_uiDateTimePickerSetTime(lua_State *L) 110 | { 111 | uiDateTimePicker *picker = UI_CHECK_OBJECT(1, DateTimePicker); 112 | struct tm ts = {0}; 113 | luaL_checktype(L, 2, LUA_TTABLE); 114 | lua_settop(L, 2); 115 | 116 | ts.tm_sec = getfield(L, "sec", 0, 0); 117 | ts.tm_min = getfield(L, "min", 0, 0); 118 | ts.tm_hour = getfield(L, "hour", 12, 0); 119 | ts.tm_mday = getfield(L, "day", -1, 0); 120 | ts.tm_mon = getfield(L, "month", -1, 1); 121 | ts.tm_year = getfield(L, "year", -1, 1900); 122 | ts.tm_isdst = getboolfield(L, "isdst"); 123 | 124 | uiDateTimePickerSetTime(picker, &ts); 125 | UI_RETURN_SELF; 126 | } 127 | 128 | static void l_uiDateTimePickerCallback(uiDateTimePicker *picker, void* arg) 129 | { 130 | lua_State *L = (lua_State *)arg; 131 | int ret = 0; 132 | 133 | lua_rawgetp(L, LUA_REGISTRYINDEX, (const void*)l_uiDateTimePickerCallback); 134 | UI_CREATE_OBJECT_REF(DateTimePicker, picker); 135 | lua_rawgetp(L, LUA_REGISTRYINDEX, picker); 136 | luaL_checktype(L, -3, LUA_TFUNCTION); 137 | luaL_checkudata(L, -2, "libui.DateTimePicker"); 138 | ret = lua_pcall(L, 2, 0, 0); 139 | if(ret!=0) 140 | { 141 | lua_pushfstring(L, "Callback function for uiDateTimePickerOnChanged fail: %s", lua_tostring(L, -1)); 142 | lua_remove(L, lua_absindex(L, -2)); 143 | lua_error(L); 144 | } 145 | } 146 | 147 | static int l_uiDateTimePickerOnChanged(lua_State *L) 148 | { 149 | uiDateTimePicker *picker = UI_CHECK_OBJECT(1, DateTimePicker); 150 | luaL_checktype(L, 2, LUA_TFUNCTION); 151 | lua_settop(L, 3); 152 | lua_pushvalue(L, 2); 153 | lua_rawsetp(L, LUA_REGISTRYINDEX, (const void*)l_uiDateTimePickerCallback); 154 | lua_pushvalue(L, 3); 155 | lua_rawsetp(L, LUA_REGISTRYINDEX, picker); 156 | 157 | uiDateTimePickerOnChanged(picker, l_uiDateTimePickerCallback, L); 158 | UI_RETURN_SELF; 159 | } 160 | 161 | static struct luaL_Reg meta_DateTimePicker[] = 162 | { 163 | { "Time", l_uiDateTimePickerTime }, 164 | { "SetTime", l_uiDateTimePickerSetTime }, 165 | { "OnChanged", l_uiDateTimePickerOnChanged }, 166 | 167 | CONTROL_COMMON_METAFIELD 168 | { NULL, NULL } 169 | }; 170 | -------------------------------------------------------------------------------- /src/ldraw.c: -------------------------------------------------------------------------------- 1 | /* uiAreaHandler */ 2 | static int l_uiAreaDrawParams_2_table(lua_State *L, uiAreaDrawParams *params) 3 | { 4 | lua_newtable(L); 5 | CREATE_USER_OBJECT(DrawContext, params->Context); 6 | lua_setfield(L, -2, "Context"); 7 | 8 | #define PARAMS_SET_NUMBER(val, name) \ 9 | lua_pushnumber(L, val); \ 10 | lua_setfield(L, -2, #name) 11 | 12 | PARAMS_SET_NUMBER(params->AreaWidth, AreaWidth); 13 | PARAMS_SET_NUMBER(params->AreaHeight, AreaHeight); 14 | 15 | PARAMS_SET_NUMBER(params->ClipX, ClipX); 16 | PARAMS_SET_NUMBER(params->ClipY, ClipY); 17 | PARAMS_SET_NUMBER(params->ClipWidth, ClipWidth); 18 | PARAMS_SET_NUMBER(params->ClipHeight, ClipWidth); 19 | #undef PARAMS_SET_NUMBER 20 | return 1; 21 | } 22 | 23 | 24 | //from: https://source.winehq.org/source/dlls/ntdll/string.c 25 | char * WINE_i64toa( 26 | long long value, /* [I] Value to be converted */ 27 | char *str, /* [O] Destination for the converted value */ 28 | int radix) /* [I] Number base for conversion */ 29 | { 30 | unsigned long long val; 31 | int negative; 32 | char buffer[65]; 33 | char *pos; 34 | int digit; 35 | 36 | if (value < 0 && radix == 10) 37 | { 38 | negative = 1; 39 | val = -value; 40 | } 41 | else 42 | { 43 | negative = 0; 44 | val = value; 45 | } /* if */ 46 | 47 | pos = &buffer[64]; 48 | *pos = '\0'; 49 | 50 | do 51 | { 52 | digit = val % radix; 53 | val = val / radix; 54 | if (digit < 10) 55 | { 56 | *--pos = '0' + digit; 57 | } 58 | else 59 | { 60 | *--pos = 'a' + digit - 10; 61 | } /* if */ 62 | } 63 | while (val != 0L); 64 | 65 | if (negative) 66 | { 67 | *--pos = '-'; 68 | } /* if */ 69 | 70 | memcpy(str, pos, &buffer[64] - pos + 1); 71 | return str; 72 | } 73 | 74 | #define lua_pushINT64(L,n) \ 75 | if(n > 9007199254740992LL || (int64_t)n < -9007199254740992LL) { \ 76 | char buf[24]; \ 77 | lua_pushstring(L, WINE_i64toa(n, buf, 10)); \ 78 | }else{ \ 79 | lua_pushnumber(L, (lua_Number)n); \ 80 | } 81 | 82 | static int l_uiAreaMouseEvent_2_table(lua_State *L, uiAreaMouseEvent *evt) 83 | { 84 | lua_newtable(L); 85 | 86 | #define PARAMS_SET_VALUE(val, type) \ 87 | lua_push##type(L, evt->val); \ 88 | lua_setfield(L, -2, #val) 89 | 90 | PARAMS_SET_VALUE(X, number); 91 | PARAMS_SET_VALUE(Y, number); 92 | 93 | PARAMS_SET_VALUE(AreaWidth, number); 94 | PARAMS_SET_VALUE(AreaHeight, number); 95 | 96 | PARAMS_SET_VALUE(Down, integer); 97 | PARAMS_SET_VALUE(Up, integer); 98 | PARAMS_SET_VALUE(Count, integer); 99 | 100 | PARAMS_SET_VALUE(Modifiers, integer); 101 | 102 | lua_pushINT64(L, evt->Held1To64); 103 | lua_setfield(L, -2, "Held1To64"); 104 | 105 | #undef PARAMS_SET_VALUE 106 | return 1; 107 | } 108 | 109 | static int l_uiAreaKeyEvent_2_table(lua_State *L, uiAreaKeyEvent *evt) 110 | { 111 | lua_newtable(L); 112 | 113 | #define PARAMS_SET_VALUE(val, type) \ 114 | lua_push##type(L, evt->val); \ 115 | lua_setfield(L, -2, #val) 116 | 117 | PARAMS_SET_VALUE(Key, integer); 118 | PARAMS_SET_VALUE(ExtKey, integer); 119 | PARAMS_SET_VALUE(Modifier, integer); 120 | PARAMS_SET_VALUE(Modifiers, integer); 121 | PARAMS_SET_VALUE(Up, boolean); 122 | 123 | #undef PARAMS_SET_VALUE 124 | return 1; 125 | } 126 | 127 | typedef struct 128 | { 129 | uiAreaHandler handler; 130 | lua_State *L; 131 | } luiAreaHandler; 132 | 133 | static void l_HandlerDraw_cb(uiAreaHandler *handler, uiArea *area, uiAreaDrawParams *params) 134 | { 135 | int err; 136 | luiAreaHandler *lh = (luiAreaHandler*)handler; 137 | lua_State *L = lh->L; 138 | 139 | /* Get the traceback function in case of error */ 140 | lua_pushcfunction(L, traceback); 141 | err = lua_gettop(L); 142 | 143 | /* Find table with callback data in registry */ 144 | lua_pushlightuserdata(L, handler); 145 | lua_gettable(L, LUA_REGISTRYINDEX); 146 | 147 | /* Get function, control userdata and callback data */ 148 | luaL_checktype(L, -1, LUA_TTABLE); 149 | lua_getfield(L, -1, "Draw"); 150 | luaL_checktype(L, -1, LUA_TFUNCTION); 151 | lua_getfield(L, -2, "SELF"); 152 | luaL_checktype(L, -1, LUA_TUSERDATA); 153 | UI_CREATE_OBJECT_REF(Area, area); 154 | l_uiAreaDrawParams_2_table(L, params); 155 | 156 | /* Call function */ 157 | if (lua_pcall(L, 3, 0, err)) 158 | { 159 | luaL_error(L, lua_tostring(L, -1)); 160 | lua_pop(L, 1); 161 | } 162 | 163 | /* Remove table with callback data in registry */ 164 | lua_pop(L, 1); 165 | /* Remove the traceback function */ 166 | lua_pop(L, 1); 167 | assert(err - 1 == lua_gettop(L)); 168 | } 169 | 170 | static void l_HandlerMouseEvent_cb(uiAreaHandler *handler, uiArea *area, uiAreaMouseEvent *evt) 171 | { 172 | int err; 173 | luiAreaHandler *lh = (luiAreaHandler*)handler; 174 | lua_State *L = lh->L; 175 | 176 | /* Get the traceback function in case of error */ 177 | lua_pushcfunction(L, traceback); 178 | err = lua_gettop(L); 179 | 180 | /* Find table with callback data in registry */ 181 | lua_pushlightuserdata(L, handler); 182 | lua_gettable(L, LUA_REGISTRYINDEX); 183 | 184 | /* Get function, control userdata and callback data */ 185 | luaL_checktype(L, -1, LUA_TTABLE); 186 | lua_getfield(L, -1, "MouseEvent"); 187 | luaL_checktype(L, -1, LUA_TFUNCTION); 188 | lua_getfield(L, -2, "SELF"); 189 | luaL_checktype(L, -1, LUA_TUSERDATA); 190 | UI_CREATE_OBJECT_REF(Area, area); 191 | l_uiAreaMouseEvent_2_table(L, evt); 192 | 193 | /* Call function */ 194 | if (lua_pcall(L, 3, 0, err)) 195 | { 196 | luaL_error(L, lua_tostring(L, -1)); 197 | lua_pop(L, 1); 198 | } 199 | 200 | /* Remove table with callback data in registry */ 201 | lua_pop(L, 1); 202 | /* Remove the traceback function */ 203 | lua_pop(L, 1); 204 | assert(err - 1 == lua_gettop(L)); 205 | } 206 | 207 | static void l_HandlerMouseCrossed_cb(uiAreaHandler *handler, uiArea *area, int left) 208 | { 209 | int err; 210 | luiAreaHandler *lh = (luiAreaHandler*)handler; 211 | lua_State *L = lh->L; 212 | 213 | /* Get the traceback function in case of error */ 214 | lua_pushcfunction(L, traceback); 215 | err = lua_gettop(L); 216 | 217 | /* Find table with callback data in registry */ 218 | lua_pushlightuserdata(L, handler); 219 | lua_gettable(L, LUA_REGISTRYINDEX); 220 | 221 | /* Get function, control userdata and callback data */ 222 | luaL_checktype(L, -1, LUA_TTABLE); 223 | lua_getfield(L, -1, "MouseCrossed"); 224 | luaL_checktype(L, -1, LUA_TFUNCTION); 225 | lua_getfield(L, -2, "SELF"); 226 | luaL_checktype(L, -1, LUA_TUSERDATA); 227 | UI_CREATE_OBJECT_REF(Area, area); 228 | lua_pushinteger(L, left); 229 | 230 | /* Call function */ 231 | if (lua_pcall(L, 3, 0, err)) 232 | { 233 | luaL_error(L, lua_tostring(L, -1)); 234 | lua_pop(L, 1); 235 | } 236 | 237 | /* Remove table with callback data in registry */ 238 | lua_pop(L, 1); 239 | /* Remove the traceback function */ 240 | lua_pop(L, 1); 241 | assert(err - 1 == lua_gettop(L)); 242 | } 243 | 244 | static void l_HandlerDragBroken_cb(uiAreaHandler *handler, uiArea *area) 245 | { 246 | int err; 247 | luiAreaHandler *lh = (luiAreaHandler*)handler; 248 | lua_State *L = lh->L; 249 | 250 | /* Get the traceback function in case of error */ 251 | lua_pushcfunction(L, traceback); 252 | err = lua_gettop(L); 253 | 254 | /* Find table with callback data in registry */ 255 | lua_pushlightuserdata(L, handler); 256 | lua_gettable(L, LUA_REGISTRYINDEX); 257 | 258 | /* Get function, control userdata and callback data */ 259 | luaL_checktype(L, -1, LUA_TTABLE); 260 | lua_getfield(L, -1, "DragBroken"); 261 | luaL_checktype(L, -1, LUA_TFUNCTION); 262 | lua_getfield(L, -2, "SELF"); 263 | luaL_checktype(L, -1, LUA_TUSERDATA); 264 | UI_CREATE_OBJECT_REF(Area, area); 265 | 266 | /* Call function */ 267 | if (lua_pcall(L, 2, 0, err)) 268 | { 269 | luaL_error(L, lua_tostring(L, -1)); 270 | lua_pop(L, 1); 271 | } 272 | 273 | /* Remove table with callback data in registry */ 274 | lua_pop(L, 1); 275 | /* Remove the traceback function */ 276 | lua_pop(L, 1); 277 | assert(err - 1 == lua_gettop(L)); 278 | } 279 | 280 | static int l_HandlerKeyEvent_cb(uiAreaHandler *handler, uiArea *area, uiAreaKeyEvent *evt) 281 | { 282 | int err, ret = 0; 283 | luiAreaHandler *lh = (luiAreaHandler*)handler; 284 | lua_State *L = lh->L; 285 | 286 | /* Get the traceback function in case of error */ 287 | lua_pushcfunction(L, traceback); 288 | err = lua_gettop(L); 289 | 290 | /* Find table with callback data in registry */ 291 | lua_pushlightuserdata(L, handler); 292 | lua_gettable(L, LUA_REGISTRYINDEX); 293 | 294 | /* Get function, control userdata and callback data */ 295 | luaL_checktype(L, -1, LUA_TTABLE); 296 | lua_getfield(L, -1, "KeyEvent"); 297 | luaL_checktype(L, -1, LUA_TFUNCTION); 298 | lua_getfield(L, -2, "SELF"); 299 | luaL_checktype(L, -1, LUA_TUSERDATA); 300 | UI_CREATE_OBJECT_REF(Area, area); 301 | l_uiAreaKeyEvent_2_table(L, evt); 302 | 303 | /* Call function */ 304 | if (lua_pcall(L, 3, 1, err) != LUA_OK) 305 | { 306 | luaL_error(L, lua_tostring(L, -1)); 307 | lua_pop(L, 1); 308 | } 309 | else 310 | { 311 | if (lua_isboolean(L, -1)) 312 | ret = lua_toboolean(L, -1); 313 | else 314 | ret = luaL_checkinteger(L, -1); 315 | lua_pop(L, 1); 316 | } 317 | /* Remove table with callback data in registry */ 318 | lua_pop(L, 1); 319 | /* Remove the traceback function */ 320 | lua_pop(L, 1); 321 | assert(err - 1 == lua_gettop(L)); 322 | return ret; 323 | } 324 | 325 | static int l_uiDrawNewAreaHandler(lua_State *L) 326 | { 327 | luiAreaHandler *lh; 328 | uiAreaHandler *handler; 329 | 330 | luaL_checktype(L, 1, LUA_TFUNCTION); 331 | luaL_checktype(L, 2, LUA_TFUNCTION); 332 | luaL_checktype(L, 3, LUA_TFUNCTION); 333 | luaL_checktype(L, 4, LUA_TFUNCTION); 334 | luaL_checktype(L, 5, LUA_TFUNCTION); 335 | 336 | lh = malloc(sizeof(luiAreaHandler)); 337 | handler = &lh->handler; 338 | lh->L = L; 339 | 340 | CREATE_USER_OBJECT(AreaHandler, handler); 341 | 342 | /* Push registery key: userdata pointer to control */ 343 | lua_pushlightuserdata(L, handler); 344 | lua_newtable(L); 345 | 346 | lua_pushvalue(L, 1); 347 | lua_setfield(L, -2, "Draw"); 348 | lua_pushvalue(L, 2); 349 | lua_setfield(L, -2, "MouseEvent"); 350 | lua_pushvalue(L, 3); 351 | lua_setfield(L, -2, "MouseCrossed"); 352 | lua_pushvalue(L, 4); 353 | lua_setfield(L, -2, "DragBroken"); 354 | lua_pushvalue(L, 5); 355 | lua_setfield(L, -2, "KeyEvent"); 356 | lua_pushvalue(L, 6); 357 | lua_setfield(L, -2, "SELF"); 358 | 359 | /* Store in registry */ 360 | lua_settable(L, LUA_REGISTRYINDEX); 361 | 362 | handler->Draw = l_HandlerDraw_cb; 363 | handler->MouseEvent = l_HandlerMouseEvent_cb; 364 | handler->MouseCrossed = l_HandlerMouseCrossed_cb; 365 | handler->DragBroken = l_HandlerDragBroken_cb; 366 | handler->KeyEvent = l_HandlerKeyEvent_cb; 367 | 368 | return 1; 369 | } 370 | 371 | static int l_uiDrawFreeAreaHandler(lua_State *L) 372 | { 373 | uiAreaHandler *handler = CHECK_USER_OBJECT(1, AreaHandler); 374 | luiAreaHandler *lh = (luiAreaHandler *)handler; 375 | lua_pushlightuserdata(L, handler); 376 | lua_pushnil(L); 377 | lua_settable(L, LUA_REGISTRYINDEX); 378 | free(lh); 379 | return 0; 380 | } 381 | 382 | static struct luaL_Reg meta_AreaHandler[] = 383 | { 384 | { "Free", l_uiDrawFreeAreaHandler }, 385 | { "__gc", l_uiDrawFreeAreaHandler }, 386 | 387 | { NULL, NULL } 388 | }; 389 | 390 | /** Path **/ 391 | static int l_uiDrawNewPath(lua_State *L) 392 | { 393 | uiDrawPath *dp = uiDrawNewPath(luaL_checkinteger(L, 1)); 394 | CREATE_USER_OBJECT(DrawPath, dp); 395 | return 1; 396 | } 397 | 398 | static int l_uiDrawFreePath(lua_State *L) 399 | { 400 | uiDrawPath **p = (uiDrawPath**)lua_touserdata(L, 1); 401 | if (*p != NULL) 402 | { 403 | uiDrawFreePath(*p); 404 | *p = NULL; 405 | } 406 | return 0; 407 | } 408 | 409 | static int l_uiDrawPathNewFigure(lua_State *L) 410 | { 411 | uiDrawPathNewFigure(CHECK_USER_OBJECT(1, DrawPath), luaL_checknumber(L, 2), luaL_checknumber(L, 3)); 412 | UI_RETURN_SELF; 413 | } 414 | 415 | static int l_uiDrawPathNewFigureWithArc(lua_State *L) 416 | { 417 | uiDrawPathNewFigureWithArc(CHECK_USER_OBJECT(1, DrawPath), 418 | luaL_checknumber(L, 2), 419 | luaL_checknumber(L, 3), 420 | luaL_checknumber(L, 4), 421 | luaL_checknumber(L, 5), 422 | luaL_checknumber(L, 6), 423 | luaL_checkboolean(L, 7)); 424 | UI_RETURN_SELF; 425 | } 426 | 427 | static int l_uiDrawPathLineTo(lua_State *L) 428 | { 429 | uiDrawPathLineTo(CHECK_USER_OBJECT(1, DrawPath), luaL_checknumber(L, 2), luaL_checknumber(L, 3)); 430 | UI_RETURN_SELF; 431 | } 432 | 433 | static int l_uiDrawPathArcTo(lua_State *L) 434 | { 435 | uiDrawPathArcTo(CHECK_USER_OBJECT(1, DrawPath), 436 | luaL_checknumber(L, 2), 437 | luaL_checknumber(L, 3), 438 | luaL_checknumber(L, 4), 439 | luaL_checknumber(L, 5), 440 | luaL_checknumber(L, 6), 441 | luaL_checkboolean(L, 7)); 442 | UI_RETURN_SELF; 443 | } 444 | 445 | static int l_uiDrawPathBezierTo(lua_State *L) 446 | { 447 | uiDrawPathBezierTo(CHECK_USER_OBJECT(1, DrawPath), 448 | luaL_checknumber(L, 2), 449 | luaL_checknumber(L, 3), 450 | luaL_checknumber(L, 4), 451 | luaL_checknumber(L, 5), 452 | luaL_checknumber(L, 6), 453 | luaL_checknumber(L, 7)); 454 | UI_RETURN_SELF; 455 | } 456 | 457 | static int l_uiDrawPathCloseFigure(lua_State *L) 458 | { 459 | uiDrawPathCloseFigure(CHECK_USER_OBJECT(1, DrawPath)); 460 | UI_RETURN_SELF; 461 | } 462 | 463 | static int l_uiDrawPathAddRectangle(lua_State *L) 464 | { 465 | uiDrawPathAddRectangle(CHECK_USER_OBJECT(1, DrawPath), 466 | luaL_checknumber(L, 2), 467 | luaL_checknumber(L, 3), 468 | luaL_checknumber(L, 4), 469 | luaL_checknumber(L, 5)); 470 | UI_RETURN_SELF; 471 | } 472 | 473 | static int l_uiDrawPathEnd(lua_State *L) 474 | { 475 | uiDrawPathEnd(CHECK_USER_OBJECT(1, DrawPath)); 476 | UI_RETURN_SELF; 477 | } 478 | 479 | static struct luaL_Reg meta_DrawPath[] = 480 | { 481 | { "NewFigure", l_uiDrawPathNewFigure }, 482 | { "NewFigureWithArc", l_uiDrawPathNewFigureWithArc }, 483 | 484 | { "LineTo", l_uiDrawPathLineTo }, 485 | { "ArcTo", l_uiDrawPathArcTo }, 486 | { "BezierTo", l_uiDrawPathBezierTo }, 487 | { "CloseFigure", l_uiDrawPathCloseFigure }, 488 | { "AddRectangle", l_uiDrawPathAddRectangle }, 489 | { "End", l_uiDrawPathEnd }, 490 | { "Free", l_uiDrawFreePath }, 491 | { "__gc", l_uiDrawFreePath }, 492 | 493 | { NULL, NULL } 494 | }; 495 | 496 | /** Matrix **/ 497 | static int l_uiDrawNewMatrix(lua_State *L) 498 | { 499 | uiDrawMatrix *matrix = malloc(sizeof(uiDrawMatrix)); 500 | memset(matrix, 0, sizeof(uiDrawMatrix)); 501 | 502 | matrix->M11 = luaL_optnumber(L, 1, 0); 503 | matrix->M12 = luaL_optnumber(L, 2, 0); 504 | matrix->M21 = luaL_optnumber(L, 3, 0); 505 | matrix->M22 = luaL_optnumber(L, 4, 0); 506 | matrix->M31 = luaL_optnumber(L, 5, 0); 507 | matrix->M32 = luaL_optnumber(L, 6, 0); 508 | 509 | CREATE_USER_OBJECT(DrawMatrix, matrix); 510 | return 1; 511 | } 512 | 513 | static int l_uiDrawFreeMatrix(lua_State *L) 514 | { 515 | free(CHECK_USER_OBJECT(1, DrawMatrix)); 516 | return 0; 517 | } 518 | static int l_uiDrawMatrixSetIdentity(lua_State *L) 519 | { 520 | uiDrawMatrixSetIdentity(CHECK_USER_OBJECT(1, DrawMatrix)); 521 | UI_RETURN_SELF; 522 | } 523 | 524 | static int l_uiDrawMatrixTranslate(lua_State *L) 525 | { 526 | uiDrawMatrixTranslate(CHECK_USER_OBJECT(1, DrawMatrix), luaL_checknumber(L, 2), luaL_checknumber(L, 3)); 527 | UI_RETURN_SELF; 528 | } 529 | 530 | static int l_uiDrawMatrixScale(lua_State *L) 531 | { 532 | uiDrawMatrixScale(CHECK_USER_OBJECT(1, DrawMatrix), 533 | luaL_checknumber(L, 2), luaL_checknumber(L, 3), 534 | luaL_checknumber(L, 4), luaL_checknumber(L, 5)); 535 | UI_RETURN_SELF; 536 | } 537 | 538 | static int l_uiDrawMatrixRotate(lua_State *L) 539 | { 540 | uiDrawMatrixRotate(CHECK_USER_OBJECT(1, DrawMatrix), 541 | luaL_checknumber(L, 2), 542 | luaL_checknumber(L, 3), 543 | luaL_checknumber(L, 4)); 544 | UI_RETURN_SELF; 545 | } 546 | 547 | static int l_uiDrawMatrixSkew(lua_State *L) 548 | { 549 | uiDrawMatrixSkew(CHECK_USER_OBJECT(1, DrawMatrix), 550 | luaL_checknumber(L, 2), luaL_checknumber(L, 3), 551 | luaL_checknumber(L, 4), luaL_checknumber(L, 5)); 552 | UI_RETURN_SELF; 553 | } 554 | 555 | static int l_uiDrawMatrixMultiply(lua_State *L) 556 | { 557 | uiDrawMatrixMultiply(CHECK_USER_OBJECT(1, DrawMatrix), CHECK_USER_OBJECT(2, DrawMatrix)); 558 | UI_RETURN_SELF; 559 | } 560 | 561 | static int l_uiDrawMatrixInvertible(lua_State *L) 562 | { 563 | lua_pushboolean(L, uiDrawMatrixInvertible(CHECK_USER_OBJECT(1, DrawMatrix))); 564 | return 1; 565 | } 566 | 567 | static int l_uiDrawMatrixInvert(lua_State *L) 568 | { 569 | lua_pushboolean(L, uiDrawMatrixInvert(CHECK_USER_OBJECT(1, DrawMatrix))); 570 | return 1; 571 | } 572 | 573 | static int l_uiDrawMatrixTransformPoint(lua_State *L) 574 | { 575 | double x, y; 576 | uiDrawMatrixTransformPoint(CHECK_USER_OBJECT(1, DrawMatrix), &x, &y); 577 | lua_pushnumber(L, x); 578 | lua_pushnumber(L, y); 579 | return 2; 580 | } 581 | 582 | static int l_uiDrawMatrixTransformSize(lua_State *L) 583 | { 584 | double x, y; 585 | uiDrawMatrixTransformSize(CHECK_USER_OBJECT(1, DrawMatrix), &x, &y); 586 | lua_pushnumber(L, x); 587 | lua_pushnumber(L, y); 588 | return 2; 589 | } 590 | 591 | static struct luaL_Reg meta_DrawMatrix[] = 592 | { 593 | { "SetIdentity", l_uiDrawMatrixSetIdentity }, 594 | { "Translate", l_uiDrawMatrixTranslate }, 595 | { "Scale", l_uiDrawMatrixScale }, 596 | { "Rotate", l_uiDrawMatrixRotate }, 597 | { "Skew", l_uiDrawMatrixSkew }, 598 | { "Multiply", l_uiDrawMatrixMultiply }, 599 | { "Invertible", l_uiDrawMatrixInvertible }, 600 | { "Invert", l_uiDrawMatrixInvert }, 601 | { "TransformPoint", l_uiDrawMatrixTransformPoint }, 602 | { "TransformSize", l_uiDrawMatrixTransformSize }, 603 | { "Free", l_uiDrawFreeMatrix }, 604 | { "__gc", l_uiDrawFreeMatrix }, 605 | 606 | { NULL, NULL } 607 | }; 608 | 609 | /* brush */ 610 | static int l_uiDrawNewBrush(lua_State *L) 611 | { 612 | uiDrawBrush *brush = malloc(sizeof(uiDrawBrush)); 613 | memset(brush, 0, sizeof(uiDrawBrush)); 614 | CREATE_USER_OBJECT(DrawBrush, brush); 615 | return 1; 616 | } 617 | 618 | static int lui_uiDrawBrushType(lua_State *L) 619 | { 620 | uiDrawBrush *brush = CHECK_USER_OBJECT(1, DrawBrush); 621 | if (lua_isnone(L, 2)) 622 | { 623 | lua_pushinteger(L, brush->Type); 624 | return 1; 625 | } 626 | brush->Type = luaL_checkinteger(L, 2); 627 | UI_RETURN_SELF; 628 | } 629 | 630 | static int lui_uiDrawBrushSolid(lua_State *L) 631 | { 632 | uiDrawBrush *brush = CHECK_USER_OBJECT(1, DrawBrush); 633 | if (lua_isnone(L, 2)) 634 | { 635 | lua_pushnumber(L, brush->R); 636 | lua_pushnumber(L, brush->G); 637 | lua_pushnumber(L, brush->B); 638 | lua_pushnumber(L, brush->A); 639 | return 4; 640 | } 641 | brush->R = luaL_checknumber(L, 2); 642 | brush->G = luaL_checknumber(L, 3); 643 | brush->B = luaL_checknumber(L, 4); 644 | brush->A = luaL_checknumber(L, 5); 645 | UI_RETURN_SELF; 646 | } 647 | 648 | 649 | static int lui_uiDrawBrushGradient(lua_State *L) 650 | { 651 | uiDrawBrush *brush = CHECK_USER_OBJECT(1, DrawBrush); 652 | if (lua_isnone(L, 2)) 653 | { 654 | lua_pushnumber(L, brush->X0); 655 | lua_pushnumber(L, brush->Y0); 656 | lua_pushnumber(L, brush->X1); 657 | lua_pushnumber(L, brush->Y1); 658 | lua_pushnumber(L, brush->OuterRadius); 659 | return 5; 660 | } 661 | brush->X0 = luaL_checknumber(L, 2); 662 | brush->Y0 = luaL_checknumber(L, 3); 663 | brush->X1 = luaL_checknumber(L, 4); 664 | brush->Y1 = luaL_checknumber(L, 5); 665 | brush->OuterRadius = luaL_checknumber(L, 6); 666 | UI_RETURN_SELF; 667 | } 668 | 669 | static struct luaL_Reg meta_DrawBrush[] = 670 | { 671 | { "Type", lui_uiDrawBrushType }, 672 | { "Solid", lui_uiDrawBrushSolid }, 673 | { "Gradient", lui_uiDrawBrushGradient }, 674 | 675 | { NULL, NULL } 676 | }; 677 | 678 | /* 679 | struct uiDrawBrush { 680 | uiDrawBrushType Type; 681 | 682 | // gradient brushes 683 | double X0; // linear: start X, radial: start X 684 | double Y0; // linear: start Y, radial: start Y 685 | double X1; // linear: end X, radial: outer circle center X 686 | double Y1; // linear: end Y, radial: outer circle center Y 687 | double OuterRadius; // radial gradients only 688 | uiDrawBrushGradientStop *Stops; 689 | size_t NumStops; 690 | // TODO extend mode 691 | // cairo: none, repeat, reflect, pad; no individual control 692 | // Direct2D: repeat, reflect, pad; no individual control 693 | // Core Graphics: none, pad; before and after individually 694 | // TODO cairo documentation is inconsistent about pad 695 | 696 | // TODO images 697 | 698 | // TODO transforms 699 | }; 700 | } 701 | */ 702 | /* StrokeParams */ 703 | 704 | static int l_uiDrawNewStrokeParams(lua_State *L) 705 | { 706 | uiDrawStrokeParams *params = malloc(sizeof(uiDrawStrokeParams)); 707 | memset(params, 0, sizeof(uiDrawStrokeParams)); 708 | CREATE_USER_OBJECT(DrawStrokeParams, params); 709 | return 1; 710 | } 711 | 712 | static int l_uiDrawtrokeParamsCap(lua_State *L) 713 | { 714 | uiDrawStrokeParams *params = CHECK_USER_OBJECT(1, DrawStrokeParams); 715 | if (lua_isnone(L, 2)) 716 | { 717 | lua_pushinteger(L, params->Cap); 718 | return 1; 719 | } 720 | params->Cap = luaL_checkinteger(L, 2); 721 | UI_RETURN_SELF; 722 | } 723 | 724 | static int l_uiDrawtrokeParamsJoin(lua_State *L) 725 | { 726 | uiDrawStrokeParams *params = CHECK_USER_OBJECT(1, DrawStrokeParams); 727 | if (lua_isnone(L, 2)) 728 | { 729 | lua_pushinteger(L, params->Join); 730 | return 1; 731 | } 732 | params->Join = luaL_checkinteger(L, 2); 733 | UI_RETURN_SELF; 734 | } 735 | 736 | static int l_uiDrawtrokeParamsThickness(lua_State *L) 737 | { 738 | uiDrawStrokeParams *params = CHECK_USER_OBJECT(1, DrawStrokeParams); 739 | if (lua_isnone(L, 2)) 740 | { 741 | lua_pushnumber(L, params->Thickness); 742 | return 1; 743 | } 744 | params->Thickness = luaL_checknumber(L, 2); 745 | UI_RETURN_SELF; 746 | } 747 | 748 | static int l_uiDrawtrokeParamsMiterLimit(lua_State *L) 749 | { 750 | uiDrawStrokeParams *params = CHECK_USER_OBJECT(1, DrawStrokeParams); 751 | if (lua_isnone(L, 2)) 752 | { 753 | lua_pushnumber(L, params->MiterLimit); 754 | return 1; 755 | } 756 | params->MiterLimit = luaL_checknumber(L, 2); 757 | UI_RETURN_SELF; 758 | } 759 | 760 | static int l_uiDrawtrokeParamsDashes(lua_State *L) 761 | { 762 | luaL_error(L, "NYI"); 763 | return 0; 764 | } 765 | 766 | static int l_uiDrawtrokeParamsDashPhase(lua_State *L) 767 | { 768 | luaL_error(L, "NYI"); 769 | return 0; 770 | } 771 | 772 | static struct luaL_Reg meta_DrawStrokeParams[] = 773 | { 774 | { "Cap", l_uiDrawtrokeParamsCap }, 775 | { "Join", l_uiDrawtrokeParamsJoin }, 776 | { "Thickness", l_uiDrawtrokeParamsThickness }, 777 | { "MiterLimit", l_uiDrawtrokeParamsMiterLimit }, 778 | { "Dashes", l_uiDrawtrokeParamsDashes }, 779 | { "DashPhase", l_uiDrawtrokeParamsDashPhase }, 780 | 781 | { NULL, NULL } 782 | }; 783 | 784 | static int l_uiDrawTransform(lua_State *L) 785 | { 786 | uiDrawTransform(CHECK_USER_OBJECT(1, DrawContext), CHECK_USER_OBJECT(2, DrawMatrix)); 787 | UI_RETURN_SELF; 788 | } 789 | 790 | static int l_uiDrawClip(lua_State *L) 791 | { 792 | uiDrawClip(CHECK_USER_OBJECT(1, DrawContext), CHECK_USER_OBJECT(2, DrawPath)); 793 | UI_RETURN_SELF; 794 | } 795 | 796 | static int l_uiDrawSave(lua_State *L) 797 | { 798 | uiDrawSave(CHECK_USER_OBJECT(1, DrawContext)); 799 | UI_RETURN_SELF; 800 | } 801 | 802 | static int l_uiDrawRestore(lua_State *L) 803 | { 804 | uiDrawRestore(CHECK_USER_OBJECT(1, DrawContext)); 805 | UI_RETURN_SELF; 806 | } 807 | 808 | static int l_uiDrawText(lua_State *L) 809 | { 810 | uiDrawText( 811 | CHECK_USER_OBJECT(1, DrawContext), 812 | CHECK_USER_OBJECT(2, DrawTextLayout), 813 | luaL_checknumber(L, 3), 814 | luaL_checknumber(L, 4) 815 | ); 816 | UI_RETURN_SELF; 817 | } 818 | 819 | static int l_uiDrawStroke(lua_State *L) 820 | { 821 | uiDrawStroke(CHECK_USER_OBJECT(1, DrawContext), CHECK_USER_OBJECT(2, DrawPath), CHECK_USER_OBJECT(3, DrawBrush), CHECK_USER_OBJECT(4, DrawStrokeParams)); 822 | UI_RETURN_SELF; 823 | } 824 | 825 | static int l_uiDrawFill(lua_State *L) 826 | { 827 | uiDrawFill(CHECK_USER_OBJECT(1, DrawContext), CHECK_USER_OBJECT(2, DrawPath), CHECK_USER_OBJECT(3, DrawBrush)); 828 | UI_RETURN_SELF; 829 | } 830 | 831 | static struct luaL_Reg meta_DrawContext[] = 832 | { 833 | { "Transform", l_uiDrawTransform }, 834 | { "Clip", l_uiDrawClip }, 835 | { "Save", l_uiDrawSave }, 836 | { "Restore", l_uiDrawRestore }, 837 | { "Text", l_uiDrawText }, 838 | { "Stroke", l_uiDrawStroke }, 839 | { "Fill", l_uiDrawFill }, 840 | 841 | { NULL, NULL } 842 | }; 843 | 844 | static int l_uiDrawFreeTextLayout(lua_State *L) 845 | { 846 | uiDrawFreeTextLayout(CHECK_USER_OBJECT(1, DrawTextLayout)); 847 | return 0; 848 | } 849 | 850 | static int l_uiDrawTextLayoutExtents(lua_State *L) 851 | { 852 | if (lua_isnone(L, 2)) 853 | { 854 | double width, height; 855 | uiDrawTextLayoutExtents(CHECK_USER_OBJECT(1, DrawTextLayout), &width, &height); 856 | 857 | lua_pushnumber(L, width); 858 | lua_pushnumber(L, height); 859 | return 2; 860 | } 861 | luaL_error(L, "NYI"); 862 | return 0; 863 | } 864 | 865 | static struct luaL_Reg meta_DrawTextLayout[] = 866 | { 867 | { "Extents", l_uiDrawTextLayoutExtents }, 868 | { "Free", l_uiDrawFreeTextLayout }, 869 | { "__gc", l_uiDrawFreeTextLayout }, 870 | 871 | { NULL, NULL } 872 | }; 873 | 874 | static int l_uiDrawNewTextLayoutParams(lua_State *L) 875 | { 876 | uiDrawTextLayoutParams *params = lua_newuserdata(L, sizeof(uiDrawTextLayoutParams)); 877 | params->String = CHECK_USER_OBJECT(1, AttributedString); 878 | params->DefaultFont = CHECK_USER_OBJECT(2, FontDescriptor); 879 | params->Width = luaL_checknumber(L, 3); 880 | params->Align = luaL_checkinteger(L, 4); 881 | 882 | CREATE_USER_OBJECT(DrawTextLayoutParams, params); 883 | return 1; 884 | } 885 | 886 | static struct luaL_Reg meta_DrawTextLayoutParams[] = 887 | { 888 | { NULL, NULL } 889 | }; 890 | 891 | static int l_uiDrawNewTextLayout(lua_State *L) 892 | { 893 | uiDrawTextLayoutParams *params = CHECK_USER_OBJECT(1, DrawTextLayoutParams); 894 | uiDrawTextLayout *layout = uiDrawNewTextLayout(params); 895 | CREATE_USER_OBJECT(DrawTextLayout, layout); 896 | return 1; 897 | } 898 | 899 | #define CREATE_DRAWMETA \ 900 | CREATE_USER_META(AreaHandler) \ 901 | CREATE_USER_META(DrawBrush) \ 902 | CREATE_USER_META(DrawPath) \ 903 | CREATE_USER_META(DrawStrokeParams) \ 904 | CREATE_USER_META(DrawTextLayout) \ 905 | CREATE_USER_META(DrawTextLayoutParams) \ 906 | CREATE_USER_META(DrawContext) \ 907 | CREATE_USER_META(DrawMatrix) \ 908 | CREATE_USER_META(DrawBrush) \ 909 | CREATE_USER_META(DrawStrokeParams) 910 | -------------------------------------------------------------------------------- /src/lentry.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewEntry(lua_State *L) 2 | { 3 | uiEntry *e = uiNewEntry(); 4 | if (!lua_isnoneornil(L, 1)) 5 | uiEntrySetText(e, luaL_checkstring(L, 1)); 6 | UI_CREATE_OBJECT(Entry, e); 7 | return 1; 8 | } 9 | 10 | static int l_uiNewPasswordEntry(lua_State *L) 11 | { 12 | uiEntry *e = uiNewPasswordEntry(); 13 | if (!lua_isnoneornil(L, 1)) 14 | uiEntrySetText(e, luaL_checkstring(L, 1)); 15 | UI_CREATE_OBJECT(Entry, e); 16 | return 1; 17 | } 18 | 19 | static int l_uiNewSearchEntry(lua_State *L) 20 | { 21 | uiEntry *e = uiNewSearchEntry(); 22 | if (!lua_isnoneornil(L, 1)) 23 | uiEntrySetText(e, luaL_checkstring(L, 1)); 24 | UI_CREATE_OBJECT(Entry, e); 25 | return 1; 26 | } 27 | 28 | static int l_uiEntryText(lua_State *L) 29 | { 30 | if (lua_isnone(L, 2)) 31 | { 32 | lua_pushstring(L, uiEntryText(UI_CHECK_OBJECT(1, Entry))); 33 | return 1; 34 | } 35 | uiEntrySetText(UI_CHECK_OBJECT(1, Entry), luaL_checkstring(L, 2)); 36 | UI_RETURN_SELF; 37 | } 38 | 39 | static void on_entry_changed(uiEntry *b, void *data) 40 | { 41 | callback(data, b, "changed"); 42 | } 43 | 44 | static int l_uiEntryOnChanged(lua_State *L) 45 | { 46 | uiEntryOnChanged(UI_CHECK_OBJECT(1, Entry), on_entry_changed, L); 47 | create_callback_data(L, 1, "changed"); 48 | UI_RETURN_SELF; 49 | } 50 | 51 | static int l_uiEntryReadOnly(lua_State *L) 52 | { 53 | if (lua_isnone(L, 2)) 54 | { 55 | lua_pushboolean(L, uiEntryReadOnly(UI_CHECK_OBJECT(1, Entry))); 56 | return 1; 57 | } 58 | uiEntrySetReadOnly(UI_CHECK_OBJECT(1, Entry), luaL_checkboolean(L, 2)); 59 | UI_RETURN_SELF; 60 | } 61 | 62 | static struct luaL_Reg meta_Entry[] = 63 | { 64 | { "Text", l_uiEntryText }, 65 | { "OnChanged", l_uiEntryOnChanged }, 66 | { "ReadOnly", l_uiEntryReadOnly }, 67 | 68 | CONTROL_COMMON_METAFIELD 69 | { NULL, NULL } 70 | }; 71 | -------------------------------------------------------------------------------- /src/lfontbutton.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewFontDescriptor(lua_State *L) 2 | { 3 | uiFontDescriptor *desc = lua_newuserdata(L, sizeof(uiFontDescriptor)); 4 | CREATE_USER_OBJECT(FontDescriptor, desc); 5 | return 1; 6 | } 7 | 8 | static int l_uiFontDescriptorFammily(lua_State *L) 9 | { 10 | uiFontDescriptor *desc = CHECK_USER_OBJECT(1, FontDescriptor); 11 | lua_pushstring(L, desc->Family); 12 | return 1; 13 | } 14 | 15 | static int l_uiFontDescriptorSize(lua_State *L) 16 | { 17 | uiFontDescriptor *desc = CHECK_USER_OBJECT(1, FontDescriptor); 18 | lua_pushnumber(L, desc->Size); 19 | return 1; 20 | } 21 | 22 | static int l_uiFontDescriptorWeight(lua_State *L) 23 | { 24 | uiFontDescriptor *desc = CHECK_USER_OBJECT(1, FontDescriptor); 25 | lua_pushinteger(L, desc->Weight); 26 | return 1; 27 | } 28 | 29 | static int l_uiFontDescriptorItalic(lua_State *L) 30 | { 31 | uiFontDescriptor *desc = CHECK_USER_OBJECT(1, FontDescriptor); 32 | lua_pushinteger(L, desc->Italic); 33 | return 1; 34 | } 35 | 36 | static int l_uiFontDescriptorStretch(lua_State *L) 37 | { 38 | uiFontDescriptor *desc = CHECK_USER_OBJECT(1, FontDescriptor); 39 | lua_pushinteger(L, desc->Stretch); 40 | return 1; 41 | } 42 | 43 | static int l_uiFreeFontButtonFont(lua_State *L) 44 | { 45 | uiFontDescriptor *desc = CHECK_USER_OBJECT(1, FontDescriptor); 46 | uiFreeFontButtonFont(desc); 47 | return 0; 48 | } 49 | 50 | static struct luaL_Reg meta_FontDescriptor[] = 51 | { 52 | { "__gc", l_uiFreeFontButtonFont }, 53 | 54 | { "Free", l_uiFreeFontButtonFont }, 55 | { "Fammily", l_uiFontDescriptorFammily }, 56 | { "Size", l_uiFontDescriptorSize }, 57 | { "Weight", l_uiFontDescriptorWeight }, 58 | { "Italic", l_uiFontDescriptorItalic }, 59 | { "Stretch", l_uiFontDescriptorStretch }, 60 | 61 | { NULL, NULL } 62 | }; 63 | 64 | static int l_uiNewFontButton(lua_State *L) 65 | { 66 | UI_CREATE_OBJECT(FontButton, uiNewFontButton()); 67 | return 1; 68 | } 69 | 70 | static int l_uiFontButtonFont(lua_State *L) 71 | { 72 | uiFontButton *font = UI_CHECK_OBJECT(1, FontButton); 73 | uiFontDescriptor *desc = lua_newuserdata(L, sizeof(uiFontDescriptor)); 74 | memset(desc, 0, sizeof(uiFontDescriptor)); 75 | uiFontButtonFont(font, desc); 76 | CREATE_USER_OBJECT(FontDescriptor, desc); 77 | return 1; 78 | } 79 | 80 | static void on_fontbutton_changed(uiFontButton *b, void *data) 81 | { 82 | callback(data, b, "changed"); 83 | } 84 | 85 | static int l_uiFontButtonOnChanged(lua_State *L) 86 | { 87 | uiFontButtonOnChanged(UI_CHECK_OBJECT(1, FontButton), on_fontbutton_changed, L); 88 | create_callback_data(L, 1, "changed"); 89 | UI_RETURN_SELF; 90 | } 91 | 92 | static struct luaL_Reg meta_FontButton[] = 93 | { 94 | { "Font", l_uiFontButtonFont }, 95 | { "OnChanged", l_uiFontButtonOnChanged }, 96 | 97 | CONTROL_COMMON_METAFIELD 98 | { NULL, NULL } 99 | }; 100 | -------------------------------------------------------------------------------- /src/lform.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewForm(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(Form, uiNewForm()); 4 | return 1; 5 | } 6 | 7 | static int l_uiFormAppend(lua_State *L) 8 | { 9 | int n = lua_gettop(L); 10 | int i; 11 | for (i = 2; i <= n; i += 3) 12 | { 13 | uiFormAppend(UI_CHECK_OBJECT(1, Form), luaL_checkstring(L, i + 0), UI_CHECK_OBJECT(i + 1, Control), luaL_checkboolean(L, i + 2)); 14 | //copy from ltab.c, need check 15 | lua_getmetatable(L, 1); 16 | lua_pushvalue(L, i + 1); 17 | luaL_ref(L, -2); 18 | } 19 | UI_RETURN_SELF; 20 | } 21 | 22 | static int l_uiFormDelete(lua_State *L) 23 | { 24 | uiFormDelete(UI_CHECK_OBJECT(1, Form), luaL_checkinteger(L, 2)); 25 | UI_RETURN_SELF; 26 | } 27 | 28 | static int l_uiFormPadded(lua_State *L) 29 | { 30 | if (lua_isnone(L, 2)) 31 | { 32 | lua_pushboolean(L, uiFormPadded(UI_CHECK_OBJECT(1, Form))); 33 | return 1; 34 | } 35 | uiFormSetPadded(UI_CHECK_OBJECT(1, Form), luaL_checkboolean(L, 2)); 36 | UI_RETURN_SELF; 37 | } 38 | 39 | static struct luaL_Reg meta_Form[] = 40 | { 41 | { "Append", l_uiFormAppend }, 42 | { "Delete", l_uiFormDelete }, 43 | { "Padded", l_uiFormPadded }, 44 | 45 | CONTROL_COMMON_METAFIELD 46 | { NULL, NULL } 47 | }; 48 | -------------------------------------------------------------------------------- /src/lgrid.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewGrid(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(Grid, uiNewGrid()); 4 | return 1; 5 | } 6 | 7 | static int l_uiGridAppend(lua_State *L) 8 | { 9 | int i; 10 | int n = lua_gettop(L); 11 | uiGrid *grid = UI_CHECK_OBJECT(1, Grid); 12 | 13 | for (i = 2; i <= n; i += 9) 14 | { 15 | int left = luaL_checkinteger(L, i + 1); 16 | int top = luaL_checkinteger(L, i + 2); 17 | int xspan = luaL_checkinteger(L, i + 3); 18 | int yspan = luaL_checkinteger(L, i + 4); 19 | int hexpand = luaL_checkboolean(L, i + 5); 20 | uiAlign halign = luaL_checkinteger(L, i + 6); 21 | int vexpand = luaL_checkboolean(L, i + 7); 22 | uiAlign valign = luaL_checkinteger(L, i + 8); 23 | uiGridAppend(grid, UI_CHECK_OBJECT(i, Control), left, top, xspan, yspan, hexpand, halign, vexpand, valign); 24 | 25 | //copy ltab.c, need check 26 | lua_getmetatable(L, 1); 27 | lua_pushvalue(L, i + 1); 28 | luaL_ref(L, -2); 29 | } 30 | UI_RETURN_SELF; 31 | } 32 | 33 | static int l_uiGridInsertAt(lua_State *L) 34 | { 35 | int n = lua_gettop(L); 36 | int i; 37 | for (i = 2; i <= n; i += 10) 38 | { 39 | uiAt at = luaL_checkinteger(L, i + 3); 40 | int xspan = luaL_checkinteger(L, i + 4); 41 | int yspan = luaL_checkinteger(L, i + 5); 42 | int hexpand = luaL_checkboolean(L, i + 6); 43 | uiAlign halign = luaL_checkinteger(L, i + 7); 44 | int vexpand = luaL_checkboolean(L, i + 8); 45 | uiAlign valign = luaL_checkinteger(L, i + 9); 46 | uiGridInsertAt(UI_CHECK_OBJECT(1, Grid), 47 | UI_CHECK_OBJECT(i, Control), 48 | UI_CHECK_OBJECT(i + 1, Control), 49 | at, xspan, yspan, hexpand, halign, vexpand, valign); 50 | 51 | //copy ltab.c, need check 52 | lua_getmetatable(L, 1); 53 | lua_pushvalue(L, i + 1); 54 | luaL_ref(L, -2); 55 | } 56 | UI_RETURN_SELF; 57 | } 58 | 59 | static int l_uiGridPadded(lua_State *L) 60 | { 61 | if (lua_isnone(L, 2)) 62 | { 63 | lua_pushboolean(L, uiGridPadded(UI_CHECK_OBJECT(1, Grid))); 64 | return 1; 65 | } 66 | uiGridSetPadded(UI_CHECK_OBJECT(1, Grid), luaL_checkboolean(L, 2)); 67 | UI_RETURN_SELF; 68 | } 69 | 70 | static struct luaL_Reg meta_Grid[] = 71 | { 72 | { "Append", l_uiGridAppend }, 73 | { "InsertAt", l_uiGridInsertAt }, 74 | { "Padded", l_uiGridPadded }, 75 | 76 | CONTROL_COMMON_METAFIELD 77 | { NULL, NULL } 78 | }; 79 | -------------------------------------------------------------------------------- /src/lgroup.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewGroup(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(Group, uiNewGroup(luaL_checkstring(L, 1))); 4 | return 1; 5 | } 6 | 7 | static int l_uiGroupTitle(lua_State *L) 8 | { 9 | if (lua_isnone(L, 2)) 10 | { 11 | lua_pushstring(L, uiGroupTitle(UI_CHECK_OBJECT(1, Group))); 12 | return 1; 13 | } 14 | uiGroupSetTitle(UI_CHECK_OBJECT(1, Group), luaL_checkstring(L, 2)); 15 | UI_RETURN_SELF; 16 | } 17 | 18 | static int l_uiGroupSetChild(lua_State *L) 19 | { 20 | uiGroupSetChild(UI_CHECK_OBJECT(1, Group), UI_CHECK_OBJECT(2, Control)); 21 | lua_getmetatable(L, 1); 22 | lua_pushvalue(L, 2); 23 | lua_pushboolean(L, 1); 24 | lua_settable(L, -3); 25 | UI_RETURN_SELF; 26 | } 27 | 28 | static int l_uiGroupMargined(lua_State *L) 29 | { 30 | if (lua_isnone(L, 2)) 31 | { 32 | lua_pushboolean(L, uiGroupMargined(UI_CHECK_OBJECT(1, Group))); 33 | return 1; 34 | } 35 | uiGroupSetMargined(UI_CHECK_OBJECT(1, Group), luaL_checkboolean(L, 2)); 36 | UI_RETURN_SELF; 37 | } 38 | 39 | static struct luaL_Reg meta_Group[] = 40 | { 41 | { "Title", l_uiGroupTitle }, 42 | { "Margined", l_uiGroupMargined }, 43 | { "SetChild", l_uiGroupSetChild }, 44 | CONTROL_COMMON_METAFIELD 45 | { NULL, NULL } 46 | }; 47 | -------------------------------------------------------------------------------- /src/limage.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewImage(lua_State* L) 2 | { 3 | double width = luaL_checknumber(L, 1); 4 | double height = luaL_checknumber(L, 2); 5 | uiImage* i = uiNewImage(width, height); 6 | UI_CREATE_OBJECT(Image, i); 7 | return 1; 8 | } 9 | 10 | static int l_uiImageAppend(lua_State* L) 11 | { 12 | uiImage *i = UI_CHECK_OBJECT(1, Image); 13 | size_t size = 0; 14 | void* pixels = (void*)luaL_tolstring(L, 2, &size); 15 | int pixelWidth = (int)luaL_checkinteger(L, 3); 16 | int pixelHeight = (int)luaL_checkinteger(L, 4); 17 | int byteStride = (int)luaL_checkinteger(L, 5); 18 | 19 | luaL_argcheck(L, size>=(size_t)(pixelHeight * byteStride), 2, 20 | "pixels need more data"); 21 | uiImageAppend(i, pixels, pixelWidth, pixelHeight, byteStride); 22 | UI_RETURN_SELF 23 | } 24 | 25 | static int l_uiImageFree(lua_State* L) 26 | { 27 | uiFreeImage(UI_CHECK_OBJECT(1, Image)); 28 | return 0; 29 | } 30 | 31 | static luaL_Reg meta_Image[] = 32 | { 33 | { "Append", l_uiImageAppend }, 34 | { "Free", l_uiImageFree }, 35 | { "__gc", l_uiImageFree }, 36 | 37 | CONTROL_COMMON_METAFIELD 38 | { NULL, NULL } 39 | }; 40 | -------------------------------------------------------------------------------- /src/llabel.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewLabel(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(Label, uiNewLabel(luaL_checkstring(L, 1))); 4 | return 1; 5 | } 6 | 7 | static int l_uiLabelText(lua_State *L) 8 | { 9 | if (lua_isnone(L, 2)) 10 | { 11 | lua_pushstring(L, uiLabelText(UI_CHECK_OBJECT(1, Label))); 12 | return 1; 13 | } 14 | uiLabelSetText(UI_CHECK_OBJECT(1, Label), luaL_checkstring(L, 2)); 15 | UI_RETURN_SELF; 16 | } 17 | 18 | 19 | static struct luaL_Reg meta_Label[] = 20 | { 21 | { "Text", l_uiLabelText }, 22 | 23 | CONTROL_COMMON_METAFIELD 24 | { NULL, NULL } 25 | }; 26 | -------------------------------------------------------------------------------- /src/lmenu.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewMenu(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(Menu, uiNewMenu(luaL_checkstring(L, 1))); 4 | return 1; 5 | } 6 | 7 | static int l_uiMenuAppendItem(lua_State *L) 8 | { 9 | UI_CREATE_OBJECT(MenuItem, uiMenuAppendItem(UI_CHECK_OBJECT(1, Menu), luaL_checkstring(L, 2))); 10 | return 1; 11 | } 12 | 13 | static int l_uiMenuAppendCheckItem(lua_State *L) 14 | { 15 | UI_CREATE_OBJECT(MenuItem, uiMenuAppendCheckItem(UI_CHECK_OBJECT(1, Menu), luaL_checkstring(L, 2))); 16 | return 1; 17 | } 18 | 19 | static int l_uiMenuAppendQuitItem(lua_State *L) 20 | { 21 | UI_CREATE_OBJECT(MenuItem, uiMenuAppendQuitItem(UI_CHECK_OBJECT(1, Menu))); 22 | return 1; 23 | } 24 | 25 | static int l_uiMenuAppendPreferencesItem(lua_State *L) 26 | { 27 | UI_CREATE_OBJECT(MenuItem, uiMenuAppendPreferencesItem(UI_CHECK_OBJECT(1, Menu))); 28 | return 1; 29 | } 30 | 31 | static int l_uiMenuAppendAboutItem(lua_State *L) 32 | { 33 | UI_CREATE_OBJECT(MenuItem, uiMenuAppendAboutItem(UI_CHECK_OBJECT(1, Menu))); 34 | return 1; 35 | } 36 | 37 | static int l_uiMenuAppendSeparator(lua_State *L) 38 | { 39 | uiMenuAppendSeparator(UI_CHECK_OBJECT(1, Menu)); 40 | return 0; 41 | } 42 | 43 | static struct luaL_Reg meta_Menu[] = 44 | { 45 | { "AppendItem", l_uiMenuAppendItem }, 46 | { "AppendCheckItem", l_uiMenuAppendCheckItem }, 47 | { "AppendQuitItem", l_uiMenuAppendQuitItem }, 48 | { "AppendPreferencesItem", l_uiMenuAppendPreferencesItem }, 49 | { "AppendAboutItem", l_uiMenuAppendAboutItem }, 50 | { "AppendSeparator", l_uiMenuAppendSeparator }, 51 | 52 | CONTROL_COMMON_METAFIELD 53 | { NULL, NULL } 54 | }; 55 | -------------------------------------------------------------------------------- /src/lmenuitem.c: -------------------------------------------------------------------------------- 1 | static int l_uiMenuItemEnable(lua_State *L) 2 | { 3 | uiMenuItemEnable(UI_CHECK_OBJECT(1, MenuItem)); 4 | UI_RETURN_SELF; 5 | } 6 | static int l_uiMenuItemDisable(lua_State *L) 7 | { 8 | uiMenuItemDisable(UI_CHECK_OBJECT(1, MenuItem)); 9 | UI_RETURN_SELF; 10 | } 11 | 12 | static int l_uiMenuItemChecked(lua_State *L) 13 | { 14 | if (lua_isnone(L, 2)) 15 | { 16 | lua_pushboolean(L, uiMenuItemChecked(UI_CHECK_OBJECT(1, MenuItem))); 17 | return 1; 18 | } 19 | uiMenuItemSetChecked(UI_CHECK_OBJECT(1, MenuItem), luaL_checkboolean(L, 2)); 20 | UI_RETURN_SELF; 21 | } 22 | 23 | static void on_menuitem_clicked(uiMenuItem *b, uiWindow* w, void *data) 24 | { 25 | callback(data, b, "clicked"); 26 | } 27 | 28 | static int l_uiMenuItemOnClicked(lua_State *L) 29 | { 30 | //TODO: 31 | uiMenuItemOnClicked(UI_CHECK_OBJECT(1, MenuItem), on_menuitem_clicked, L); 32 | create_callback_data(L, 1, "clicked"); 33 | UI_RETURN_SELF; 34 | } 35 | 36 | static struct luaL_Reg meta_MenuItem[] = 37 | { 38 | { "Checked", l_uiMenuItemChecked }, 39 | { "OnClicked", l_uiMenuItemOnClicked }, 40 | 41 | CONTROL_COMMON_METAFIELD 42 | 43 | { "Enable", l_uiMenuItemEnable }, 44 | { "Disable", l_uiMenuItemDisable }, 45 | 46 | { NULL, NULL } 47 | }; 48 | -------------------------------------------------------------------------------- /src/lmultiline.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewMultilineEntry(lua_State *L) 2 | { 3 | uiMultilineEntry *ml = uiNewMultilineEntry(); 4 | if (!lua_isnoneornil(L, 1)) 5 | uiMultilineEntrySetText(ml, luaL_checkstring(L, 1)); 6 | UI_CREATE_OBJECT(MultilineEntry, ml); 7 | return 1; 8 | } 9 | 10 | static int l_uiNewNonWrappingMultilineEntry(lua_State *L) 11 | { 12 | uiMultilineEntry *ml = uiNewNonWrappingMultilineEntry(); 13 | if (!lua_isnoneornil(L, 1)) 14 | uiMultilineEntrySetText(ml, luaL_checkstring(L, 1)); 15 | UI_CREATE_OBJECT(MultilineEntry, ml); 16 | return 1; 17 | } 18 | 19 | static int l_uiMultilineEntryText(lua_State *L) 20 | { 21 | if (lua_isnone(L, 2)) 22 | { 23 | lua_pushstring(L, uiMultilineEntryText(UI_CHECK_OBJECT(1, MultilineEntry))); 24 | return 1; 25 | } 26 | uiMultilineEntrySetText(UI_CHECK_OBJECT(1, MultilineEntry), luaL_checkstring(L, 2)); 27 | UI_RETURN_SELF; 28 | } 29 | 30 | static int l_uiMultilineEntryAppend(lua_State *L) 31 | { 32 | uiMultilineEntryAppend(UI_CHECK_OBJECT(1, MultilineEntry), luaL_checkstring(L, 2)); 33 | UI_RETURN_SELF; 34 | } 35 | 36 | static void on_multilineentry_changed(uiMultilineEntry *b, void *data) 37 | { 38 | callback(data, b, "changed"); 39 | } 40 | 41 | static int l_uiMultilineEntryOnChanged(lua_State *L) 42 | { 43 | uiMultilineEntryOnChanged(UI_CHECK_OBJECT(1, MultilineEntry), on_multilineentry_changed, L); 44 | create_callback_data(L, 1, "changed"); 45 | UI_RETURN_SELF; 46 | } 47 | 48 | static int l_uiMultilineEntryReadOnly(lua_State *L) 49 | { 50 | if (lua_isnone(L, 2)) 51 | { 52 | lua_pushboolean(L, uiMultilineEntryReadOnly(UI_CHECK_OBJECT(1, MultilineEntry))); 53 | return 1; 54 | } 55 | uiMultilineEntrySetReadOnly(UI_CHECK_OBJECT(1, MultilineEntry), luaL_checkboolean(L, 2)); 56 | UI_RETURN_SELF; 57 | } 58 | 59 | static struct luaL_Reg meta_MultilineEntry[] = 60 | { 61 | { "Text", l_uiMultilineEntryText }, 62 | { "Append", l_uiMultilineEntryAppend }, 63 | { "OnChanged", l_uiMultilineEntryOnChanged }, 64 | { "ReadOnly", l_uiMultilineEntryReadOnly }, 65 | 66 | CONTROL_COMMON_METAFIELD 67 | { NULL, NULL } 68 | }; 69 | -------------------------------------------------------------------------------- /src/lprogressbar.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewProgressBar(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(ProgressBar, uiNewProgressBar()); 4 | return 1; 5 | } 6 | 7 | static int l_uiProgressBarValue(lua_State *L) 8 | { 9 | if (lua_isnone(L, 2)) 10 | { 11 | lua_pushinteger(L, uiProgressBarValue(UI_CHECK_OBJECT(1, ProgressBar))); 12 | } 13 | uiProgressBarSetValue(UI_CHECK_OBJECT(1, ProgressBar), luaL_checkinteger(L, 2)); 14 | UI_RETURN_SELF; 15 | } 16 | 17 | static struct luaL_Reg meta_ProgressBar[] = 18 | { 19 | { "Value", l_uiProgressBarValue }, 20 | 21 | CONTROL_COMMON_METAFIELD 22 | { NULL, NULL } 23 | }; 24 | -------------------------------------------------------------------------------- /src/lradiobuttons.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewRadioButtons(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(RadioButtons, uiNewRadioButtons()); 4 | return 1; 5 | } 6 | 7 | static int l_uiRadioButtonsAppend(lua_State *L) 8 | { 9 | int n = lua_gettop(L); 10 | int i; 11 | for (i = 2; i <= n; i++) 12 | { 13 | const char *text = luaL_checkstring(L, i); 14 | uiRadioButtonsAppend(UI_CHECK_OBJECT(1, RadioButtons), text); 15 | } 16 | UI_RETURN_SELF; 17 | } 18 | 19 | static int l_uiRadioButtonsSelected(lua_State *L) 20 | { 21 | if (lua_isnone(L, 2)) 22 | { 23 | lua_pushinteger(L, uiRadioButtonsSelected(UI_CHECK_OBJECT(1, RadioButtons))); 24 | return 1; 25 | } 26 | uiRadioButtonsSetSelected(UI_CHECK_OBJECT(1, RadioButtons), luaL_checkinteger(L, 2));; 27 | UI_RETURN_SELF; 28 | } 29 | 30 | static void on_radiobutton_selected(uiRadioButtons *b, void *data) 31 | { 32 | callback(data, b, "selected"); 33 | } 34 | 35 | static int l_uiRadioButtonsOnSelected(lua_State *L) 36 | { 37 | uiRadioButtonsOnSelected(UI_CHECK_OBJECT(1, RadioButtons), on_radiobutton_selected, L); 38 | create_callback_data(L, 1, "selected"); 39 | UI_RETURN_SELF; 40 | } 41 | 42 | static struct luaL_Reg meta_RadioButtons[] = 43 | { 44 | { "Append", l_uiRadioButtonsAppend }, 45 | { "Selected", l_uiRadioButtonsSelected }, 46 | { "OnSelected", l_uiRadioButtonsOnSelected }, 47 | 48 | CONTROL_COMMON_METAFIELD 49 | { NULL, NULL } 50 | }; 51 | 52 | -------------------------------------------------------------------------------- /src/lseparator.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewHorizontalSeparator(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(Separator, uiNewHorizontalSeparator()); 4 | return 1; 5 | } 6 | 7 | static int l_uiNewVerticalSeparator(lua_State *L) 8 | { 9 | UI_CREATE_OBJECT(Separator, uiNewVerticalSeparator()); 10 | return 1; 11 | } 12 | 13 | static struct luaL_Reg meta_Separator[] = 14 | { 15 | CONTROL_COMMON_METAFIELD 16 | 17 | { NULL, NULL } 18 | }; 19 | -------------------------------------------------------------------------------- /src/lslider.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewSlider(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(Slider, uiNewSlider(luaL_checkinteger(L, 1), luaL_checkinteger(L, 2))); 4 | return 1; 5 | } 6 | 7 | static int l_uiSliderValue(lua_State *L) 8 | { 9 | if (lua_isnone(L, 2)) 10 | { 11 | lua_pushinteger(L, uiSliderValue(UI_CHECK_OBJECT(1, Slider))); 12 | return 1; 13 | } 14 | uiSliderSetValue(UI_CHECK_OBJECT(1, Slider), luaL_checkinteger(L, 2)); 15 | UI_RETURN_SELF; 16 | } 17 | 18 | static void on_slider_changed(uiSlider *b, void *data) 19 | { 20 | callback(data, b, "changed"); 21 | } 22 | 23 | static int l_uiSliderOnChanged(lua_State *L) 24 | { 25 | uiSliderOnChanged(UI_CHECK_OBJECT(1, Slider), on_slider_changed, L); 26 | create_callback_data(L, 1, "changed"); 27 | UI_RETURN_SELF; 28 | } 29 | 30 | static struct luaL_Reg meta_Slider[] = 31 | { 32 | { "Value", l_uiSliderValue }, 33 | { "OnChanged", l_uiSliderOnChanged }, 34 | 35 | CONTROL_COMMON_METAFIELD 36 | { NULL, NULL } 37 | }; 38 | -------------------------------------------------------------------------------- /src/lspinbox.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewSpinbox(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(Spinbox, uiNewSpinbox(luaL_checkinteger(L, 1), luaL_checkinteger(L, 2))); 4 | return 1; 5 | } 6 | 7 | static int l_uiSpinboxValue(lua_State *L) 8 | { 9 | if (lua_isnone(L, 2)) 10 | { 11 | lua_pushinteger(L, uiSpinboxValue(UI_CHECK_OBJECT(1, Spinbox))); 12 | return 1; 13 | } 14 | uiSpinboxSetValue(UI_CHECK_OBJECT(1, Spinbox), luaL_checkinteger(L, 2)); 15 | UI_RETURN_SELF; 16 | } 17 | 18 | static void on_spinbox_changed(uiSpinbox *b, void *data) 19 | { 20 | callback(data, b, "changed"); 21 | } 22 | 23 | static int l_uiSpinboxOnChanged(lua_State *L) 24 | { 25 | uiSpinboxOnChanged(UI_CHECK_OBJECT(1, Spinbox), on_spinbox_changed, L); 26 | create_callback_data(L, 1, "changed"); 27 | UI_RETURN_SELF; 28 | } 29 | 30 | static struct luaL_Reg meta_Spinbox[] = 31 | { 32 | { "Value", l_uiSpinboxValue }, 33 | { "OnChanged", l_uiSpinboxOnChanged }, 34 | 35 | CONTROL_COMMON_METAFIELD 36 | { NULL, NULL } 37 | }; 38 | -------------------------------------------------------------------------------- /src/ltab.c: -------------------------------------------------------------------------------- 1 | static int l_uiNewTab(lua_State *L) 2 | { 3 | UI_CREATE_OBJECT(Tab, uiNewTab()); 4 | return 1; 5 | } 6 | 7 | static int l_uiTabAppend(lua_State *L) 8 | { 9 | int n = lua_gettop(L); 10 | int i; 11 | for (i = 2; i <= n; i += 2) 12 | { 13 | uiTabAppend(UI_CHECK_OBJECT(1, Tab), luaL_checkstring(L, i + 0), UI_CHECK_OBJECT(i + 1, Control)); 14 | lua_getmetatable(L, 1); 15 | lua_pushvalue(L, i + 1); 16 | luaL_ref(L, -2); 17 | } 18 | UI_RETURN_SELF; 19 | } 20 | 21 | static int l_uiTabInsertAt(lua_State *L) 22 | { 23 | uiTabInsertAt(UI_CHECK_OBJECT(1, Tab), luaL_checkstring(L, 2), luaL_checkinteger(L, 3), UI_CHECK_OBJECT(4, Control)); 24 | UI_RETURN_SELF; 25 | } 26 | 27 | static int l_uiTabDelete(lua_State *L) 28 | { 29 | uiTabDelete(UI_CHECK_OBJECT(1, Tab), luaL_checkinteger(L, 2)); 30 | UI_RETURN_SELF; 31 | } 32 | 33 | static int l_uiTabNumPages(lua_State *L) 34 | { 35 | lua_pushinteger(L, uiTabNumPages(UI_CHECK_OBJECT(1, Tab))); 36 | return 1; 37 | } 38 | 39 | static int L_uiTabMargined(lua_State *L) 40 | { 41 | if (lua_isnone(L, 3)) 42 | { 43 | lua_pushboolean(L, uiTabMargined(UI_CHECK_OBJECT(1, Tab), luaL_checkinteger(L, 2))); 44 | return 1; 45 | } 46 | uiTabSetMargined(UI_CHECK_OBJECT(1, Tab), luaL_checkinteger(L, 2), luaL_checkboolean(L, 3)); 47 | UI_RETURN_SELF; 48 | } 49 | 50 | static struct luaL_Reg meta_Tab[] = 51 | { 52 | { "Append", l_uiTabAppend }, 53 | { "InsertAt", l_uiTabInsertAt }, 54 | { "Delete", l_uiTabDelete }, 55 | { "NumPages", l_uiTabNumPages }, 56 | { "Margined", L_uiTabMargined }, 57 | 58 | CONTROL_COMMON_METAFIELD 59 | { NULL, NULL } 60 | }; 61 | -------------------------------------------------------------------------------- /src/ltable.c: -------------------------------------------------------------------------------- 1 | #include "lui.h" 2 | 3 | // uiTableValue stores a value to be passed along uiTable and 4 | // uiTableModel. 5 | // 6 | // uiTableValues are immutable and the uiTableModel and uiTable 7 | // take ownership of the uiTableValue object once returned, copying 8 | // its contents as necessary. 9 | 10 | static int l_uiTableValueNew(lua_State *L) 11 | { 12 | uiTableValue *v = NULL; 13 | int top = lua_gettop(L); 14 | if (top == 1) 15 | { 16 | int typ = lua_type(L, 1); 17 | switch (typ) 18 | { 19 | case LUA_TNUMBER: 20 | { 21 | int iv = lua_tointeger(L, 1); 22 | v = uiNewTableValueInt(iv); 23 | break; 24 | } 25 | case LUA_TSTRING: 26 | { 27 | const char *sv = lua_tostring(L, 1); 28 | v = uiNewTableValueString(sv); 29 | break; 30 | } 31 | case LUA_TUSERDATA: 32 | { 33 | uiImage *img = CHECK_USER_OBJECT(1, Image); 34 | v = uiNewTableValueImage(img); 35 | break; 36 | } 37 | default: 38 | luaL_error(L, "only support number, string, uiImage when only 1 arg"); 39 | break; 40 | } 41 | } 42 | else if (top == 4) 43 | { 44 | double r = luaL_checknumber(L, 1); 45 | double g = luaL_checknumber(L, 2); 46 | double b = luaL_checknumber(L, 3); 47 | double a = luaL_checknumber(L, 4); 48 | v = uiNewTableValueColor(r, g, b, a); 49 | } 50 | CREATE_USER_OBJECT(TableValue, v); 51 | return 1; 52 | } 53 | 54 | static int l_uiTableValueFree(lua_State *L) 55 | { 56 | uiTableValue *v = CHECK_USER_OBJECT(1, TableValue); 57 | uiFreeTableValue(v); 58 | return 0; 59 | } 60 | 61 | static int l_uiTableValueGetType(lua_State *L) 62 | { 63 | const uiTableValue *v = CHECK_USER_OBJECT(1, TableValue); 64 | uiTableValueType typ = uiTableValueGetType(v); 65 | lua_pushinteger(L, typ); 66 | return 1; 67 | } 68 | 69 | static int l_uiTableValueValue(lua_State *L) 70 | { 71 | int ret = 1; 72 | const uiTableValue *v = CHECK_USER_OBJECT(1, TableValue); 73 | uiTableValueType typ = uiTableValueGetType(v); 74 | switch (typ) 75 | { 76 | case uiTableValueTypeString: 77 | { 78 | const char *vs = uiTableValueString(v); 79 | lua_pushstring(L, vs); 80 | break; 81 | } 82 | case uiTableValueTypeInt: 83 | { 84 | int iv = uiTableValueInt(v); 85 | lua_pushinteger(L, iv); 86 | break; 87 | } 88 | case uiTableValueTypeColor: 89 | { 90 | double r, g, b, a; 91 | uiTableValueColor(v, &r, &g, &b, &a); 92 | ret = 4; 93 | break; 94 | } 95 | case uiTableValueTypeImage: 96 | { 97 | uiImage *img = uiTableValueImage(v); 98 | CREATE_USER_OBJECT(Image, img); 99 | break; 100 | } 101 | default: 102 | lua_pushnil(L); 103 | } 104 | return ret; 105 | } 106 | 107 | static struct luaL_Reg meta_TableValue[] = 108 | { 109 | { "GetType", l_uiTableValueGetType }, 110 | { "Value", l_uiTableValueValue }, 111 | { "Free", l_uiTableValueFree }, 112 | { "__gc", l_uiTableValueFree }, 113 | 114 | { NULL, NULL} 115 | }; 116 | 117 | static int l_uiNewTableModelHandler(lua_State *L) 118 | { 119 | uiTableModelHandler *handler = (uiTableModelHandler *)malloc(sizeof(uiTableModelHandler)); 120 | CREATE_USER_OBJECT(TableModelHandler, handler); 121 | return 1; 122 | } 123 | 124 | static int l_uiNewTableModel(lua_State *L) 125 | { 126 | uiTableModelHandler *mh = CHECK_USER_OBJECT(1, TableModelHandler); 127 | uiTableModel *model = uiNewTableModel(mh); 128 | CREATE_USER_OBJECT(TableModel, model); 129 | return 1; 130 | } 131 | 132 | static int l_TableModleHandlerNumColumns(lua_State *L) 133 | { 134 | uiTableModelHandler *h = CHECK_USER_OBJECT(1, TableModelHandler); 135 | uiTableModel *m = CHECK_USER_OBJECT(2, TableModel); 136 | int ret = h->NumColumns(h, m); 137 | lua_pushinteger(L, ret); 138 | return 1; 139 | } 140 | 141 | static int l_TableModleHandlerColumnType(lua_State *L) 142 | { 143 | uiTableModelHandler *h = CHECK_USER_OBJECT(1, TableModelHandler); 144 | uiTableModel *m = CHECK_USER_OBJECT(2, TableModel); 145 | int col = luaL_checkinteger(L, 3); 146 | int ret = h->ColumnType(h, m, col); 147 | lua_pushinteger(L, ret); 148 | return 1; 149 | } 150 | 151 | static int l_TableModleHandlerNumRows(lua_State *L) 152 | { 153 | uiTableModelHandler *h = CHECK_USER_OBJECT(1, TableModelHandler); 154 | uiTableModel *m = CHECK_USER_OBJECT(2, TableModel); 155 | int ret = h->NumRows(h, m); 156 | lua_pushinteger(L, ret); 157 | return 1; 158 | } 159 | 160 | static int l_TableModleHandlerCellValue(lua_State *L) 161 | { 162 | uiTableModelHandler *h = CHECK_USER_OBJECT(1, TableModelHandler); 163 | uiTableModel *m = CHECK_USER_OBJECT(2, TableModel); 164 | int row = luaL_checkinteger(L, 3); 165 | int col = luaL_checkinteger(L, 4); 166 | uiTableValue *val; 167 | if (lua_isnone(L, 5)==0) 168 | { 169 | val = h->CellValue(h, m, row, col); 170 | CREATE_USER_OBJECT(TableValue, val); 171 | } 172 | else 173 | { 174 | val = CHECK_USER_OBJECT(5, TableValue); 175 | h->SetCellValue(h, m, row, col, val); 176 | lua_pushvalue(L, 5); 177 | } 178 | return 1; 179 | } 180 | 181 | static struct luaL_Reg meta_TableModelHandler[] = 182 | { 183 | { "NewTableModel", l_uiNewTableModel }, 184 | { "NumColumns", l_TableModleHandlerNumColumns }, 185 | { "ColumnType", l_TableModleHandlerColumnType }, 186 | { "NumRows", l_TableModleHandlerNumRows }, 187 | { "CellValue", l_TableModleHandlerCellValue }, 188 | 189 | { NULL, NULL } 190 | }; 191 | 192 | static int l_uiFreeTableModel(lua_State *L) 193 | { 194 | uiTableModel *m = CHECK_USER_OBJECT(1, TableModel); 195 | uiFreeTableModel(m); 196 | return 0; 197 | } 198 | 199 | static int l_uiTableModelRowInserted(lua_State *L) 200 | { 201 | uiTableModel *m = CHECK_USER_OBJECT(1, TableModel); 202 | int newIndex = luaL_checkinteger(L, 2); 203 | uiTableModelRowInserted(m, newIndex); 204 | UI_RETURN_SELF; 205 | } 206 | 207 | static int l_uiTableModelRowChanged(lua_State *L) 208 | { 209 | uiTableModel *m = CHECK_USER_OBJECT(1, TableModel); 210 | int index = luaL_checkinteger(L, 2); 211 | uiTableModelRowChanged(m, index); 212 | UI_RETURN_SELF; 213 | } 214 | 215 | static int l_uiTableModelRowDeleted(lua_State *L) 216 | { 217 | uiTableModel *m = CHECK_USER_OBJECT(1, TableModel); 218 | int index = luaL_checkinteger(L, 2); 219 | uiTableModelRowDeleted(m, index); 220 | UI_RETURN_SELF; 221 | } 222 | 223 | static int l_uiNewTableParams(lua_State *L) 224 | { 225 | uiTableModel *Model = CHECK_USER_OBJECT(1, TableModel); 226 | int RowBackgroundColorModelColumn = luaL_checkinteger(L, 1); 227 | uiTableParams *params = lua_newuserdata(L, sizeof(uiTableParams)); 228 | params->Model = Model; 229 | params->RowBackgroundColorModelColumn = RowBackgroundColorModelColumn; 230 | //FIXME: set metatable 231 | return 1; 232 | } 233 | 234 | static struct luaL_Reg meta_TableModel[] = 235 | { 236 | { "RowInserted", l_uiTableModelRowInserted }, 237 | { "RowChanged", l_uiTableModelRowChanged }, 238 | { "RowDeleted", l_uiTableModelRowDeleted }, 239 | { "NewTableParams", l_uiNewTableParams }, 240 | { "Free", l_uiFreeTableModel }, 241 | { "__gc", l_uiFreeTableModel }, 242 | 243 | { NULL, NULL} 244 | }; 245 | 246 | // uiTableModelColumnNeverEditable and 247 | // uiTableModelColumnAlwaysEditable are the value of an editable 248 | // model column parameter to one of the uiTable create column 249 | // functions; if used, that jparticular uiTable colum is not editable 250 | // by the user and always editable by the user, respectively. 251 | 252 | 253 | static int l_uiNewTableTextColumnOptionalParams(lua_State *L) 254 | { 255 | int ColorModelColumn = luaL_checkinteger(L, 1); 256 | uiTableTextColumnOptionalParams *params = lua_newuserdata(L, sizeof(uiTableTextColumnOptionalParams)); 257 | params->ColorModelColumn = ColorModelColumn; 258 | //FIXME: set metatable 259 | return 1; 260 | } 261 | 262 | static struct luaL_Reg meta_TableParams[] = 263 | { 264 | { "NewTableParams", l_uiNewTableParams }, 265 | { "", l_uiTableValueValue }, 266 | { "Free", l_uiTableValueFree }, 267 | { "__gc", l_uiTableValueFree }, 268 | 269 | { NULL, NULL} 270 | }; 271 | 272 | static int l_uiTableAppendTextColumn(lua_State *L) 273 | { 274 | uiTable *tab = UI_CHECK_OBJECT(1, Table); 275 | const char *name = luaL_checkstring(L, 2); 276 | int textModelColumn = luaL_checkinteger(L, 3); 277 | int textEditableModelColumn = luaL_checkinteger(L, 4); 278 | uiTableTextColumnOptionalParams *textParams = 279 | lua_isnoneornil(L, 5) ? NULL : CHECK_USER_OBJECT(5, TableTextColumnOptionalParams); 280 | 281 | uiTableAppendTextColumn(tab, 282 | name, 283 | textModelColumn, 284 | textEditableModelColumn, 285 | textParams); 286 | UI_RETURN_SELF; 287 | } 288 | 289 | static int l_uiTableAppendImageColumn(lua_State *L) 290 | { 291 | uiTable *tab = UI_CHECK_OBJECT(1, Table); 292 | const char *name = luaL_checkstring(L, 2); 293 | int imageModelColumn = luaL_checkinteger(L, 3); 294 | 295 | uiTableAppendImageColumn(tab, name, imageModelColumn); 296 | UI_RETURN_SELF; 297 | } 298 | 299 | static int l_uiTableAppendImageTextColumn(lua_State *L) 300 | { 301 | uiTable *tab = UI_CHECK_OBJECT(1, Table); 302 | const char *name = luaL_checkstring(L, 2); 303 | int imageModelColumn = luaL_checkinteger(L, 3); 304 | int textModelColumn = luaL_checkinteger(L, 4); 305 | int textEditableModelColumn = luaL_checkinteger(L, 5); 306 | uiTableTextColumnOptionalParams *textParams = 307 | lua_isnoneornil(L, 6) ? NULL : CHECK_USER_OBJECT(6, TableTextColumnOptionalParams); 308 | 309 | uiTableAppendImageTextColumn(tab, 310 | name, 311 | imageModelColumn, 312 | textModelColumn, 313 | textEditableModelColumn, 314 | textParams); 315 | UI_RETURN_SELF; 316 | } 317 | 318 | static int l_uiTableAppendCheckboxColumn(lua_State *L) 319 | { 320 | uiTable *tab = UI_CHECK_OBJECT(1, Table); 321 | const char *name = luaL_checkstring(L, 2); 322 | int checkboxModelColumn = luaL_checkinteger(L, 3); 323 | int checkboxEditableModelColumn = luaL_checkinteger(L, 4); 324 | 325 | uiTableAppendCheckboxColumn(tab, 326 | name, 327 | checkboxModelColumn, 328 | checkboxEditableModelColumn); 329 | 330 | UI_RETURN_SELF; 331 | } 332 | 333 | static int l_uiTableAppendCheckboxTextColumn(lua_State *L) 334 | { 335 | uiTable *tab = UI_CHECK_OBJECT(1, Table); 336 | const char *name = luaL_checkstring(L, 2); 337 | 338 | int checkboxModelColumn = luaL_checkinteger(L, 3); 339 | int checkboxEditableModelColumn = luaL_checkinteger(L, 4); 340 | int textModelColumn = luaL_checkinteger(L, 5); 341 | int textEditableModelColumn = luaL_checkinteger(L, 6); 342 | uiTableTextColumnOptionalParams *textParams = 343 | lua_isnoneornil(L, 7) ? NULL : CHECK_USER_OBJECT(7, TableTextColumnOptionalParams); 344 | 345 | uiTableAppendCheckboxTextColumn(tab, 346 | name, 347 | checkboxModelColumn, 348 | checkboxEditableModelColumn, 349 | textModelColumn, 350 | textEditableModelColumn, 351 | textParams); 352 | UI_RETURN_SELF; 353 | } 354 | 355 | static int l_uiTableAppendProgressBarColumn(lua_State *L) 356 | { 357 | uiTable *tab = UI_CHECK_OBJECT(1, Table); 358 | const char *name = luaL_checkstring(L, 2); 359 | int column = luaL_checkinteger(L, 3); 360 | 361 | uiTableAppendProgressBarColumn(tab, name, column); 362 | UI_RETURN_SELF; 363 | } 364 | 365 | static int l_uiTableAppendButtonColumn(lua_State *L) 366 | { 367 | uiTable *tab = UI_CHECK_OBJECT(1, Table); 368 | const char *name = luaL_checkstring(L, 2); 369 | int cols = luaL_checkinteger(L, 3); 370 | int clickableColumn = luaL_checkinteger(L, 4); 371 | 372 | uiTableAppendButtonColumn(tab, name, cols, clickableColumn); 373 | UI_RETURN_SELF; 374 | } 375 | 376 | static int l_uiNewTable(lua_State *L) 377 | { 378 | uiTableParams *params = CHECK_USER_OBJECT(1, TableParams); 379 | uiTable *tab = uiNewTable(params); 380 | UI_CREATE_OBJECT(Table, tab); 381 | return 1; 382 | } 383 | 384 | static struct luaL_Reg meta_Table[] = 385 | { 386 | { "AppendButtonColomn", l_uiTableAppendButtonColumn }, 387 | { "AppendCheckboxColumn", l_uiTableAppendCheckboxColumn }, 388 | { "AppendCheckboxTextColumn", l_uiTableAppendCheckboxTextColumn }, 389 | { "AppendImangeColumn", l_uiTableAppendImageColumn }, 390 | { "AppendImangeTextColumn", l_uiTableAppendImageTextColumn }, 391 | { "AppendProgressBarColumn", l_uiTableAppendProgressBarColumn }, 392 | { "AppendTextColumn", l_uiTableAppendTextColumn }, 393 | 394 | CONTROL_COMMON_METAFIELD 395 | { NULL, NULL} 396 | }; 397 | -------------------------------------------------------------------------------- /src/lui.c: -------------------------------------------------------------------------------- 1 | #include "lui.h" 2 | 3 | static lua_State* _main_L= NULL; 4 | 5 | inline static int luaL_checkboolean(lua_State *L, int n) 6 | { 7 | luaL_checktype(L, n, LUA_TBOOLEAN); 8 | return lua_toboolean(L, n); 9 | } 10 | 11 | /* make libui object felixble */ 12 | struct wrap 13 | { 14 | uiControl *control; 15 | int ref; 16 | }; 17 | 18 | inline static void* check_object(lua_State *L, int n, const char* cls) 19 | { 20 | void *p = luaL_testudata(L, n, cls); 21 | if (p==NULL) 22 | { 23 | p = auxiliar_checkgroup(L, cls, n); 24 | } 25 | 26 | return (((struct wrap*)p)->control); 27 | } 28 | 29 | #define UI_RETURN_SELF lua_pushvalue(L, 1); return 1; 30 | 31 | #define UI_CREATE_META(t) \ 32 | luaL_newmetatable(L, "libui." #t); \ 33 | lua_pushstring(L, "__index"); \ 34 | lua_newtable(L); \ 35 | lua_pushstring(L, "class"); \ 36 | lua_pushstring(L, "libui." #t); \ 37 | lua_rawset(L, -3); \ 38 | luaL_setfuncs(L, meta_ ## t, 0); \ 39 | lua_rawset(L, -3); \ 40 | lua_pushstring(L, "__gc"); \ 41 | lua_pushcfunction(L, l_uigc); \ 42 | lua_rawset(L, -3); \ 43 | lua_pushstring(L, "__tostring"); \ 44 | lua_pushcfunction(L, auxiliar_tostring); \ 45 | lua_rawset(L, -3); \ 46 | lua_pop(L, 1); 47 | 48 | #define UI_CHECK_OBJECT(n, t) \ 49 | check_object(L, n, "libui." #t) 50 | 51 | #define UI_CREATE_OBJECT(t, c) \ 52 | struct wrap *w = lua_newuserdata(L, sizeof(struct wrap)); \ 53 | w->control = uiControl(c); \ 54 | w->ref = 0; \ 55 | luaL_setmetatable(L, "libui." #t); 56 | 57 | #define UI_CREATE_OBJECT_REF(t, c) \ 58 | struct wrap *w = lua_newuserdata(L, sizeof(struct wrap)); \ 59 | w->control = uiControl(c); \ 60 | w->ref = 1; \ 61 | luaL_setmetatable(L, "libui." #t); 62 | 63 | #define UI_SET_GROUP(cls, grp) \ 64 | auxiliar_add2group(L, "libui." #cls, "libui." #grp); 65 | 66 | #define UI_CHECK_GROUP(n, t) \ 67 | auxiliar_checkgroup(L, "libui." #t, n) 68 | 69 | #define CREATE_USER_META(t) \ 70 | luaL_newmetatable(L, "libui.user." #t); \ 71 | lua_pushstring(L, "__index"); \ 72 | lua_newtable(L); \ 73 | lua_pushstring(L, "class"); \ 74 | lua_pushstring(L, "libui.user." #t); \ 75 | lua_rawset(L, -3); \ 76 | luaL_setfuncs(L, meta_ ## t, 0); \ 77 | lua_rawset(L, -3); \ 78 | lua_pushstring(L, "__tostring"); \ 79 | lua_pushcfunction(L, auxiliar_tostring); \ 80 | lua_rawset(L, -3); \ 81 | lua_pop(L, 1); 82 | 83 | #define CREATE_USER_OBJECT(t, c) \ 84 | *(ui ## t**)lua_newuserdata(L, sizeof(ui ## t*)) = c; \ 85 | luaL_setmetatable(L, "libui.user." #t); 86 | 87 | #define CHECK_USER_OBJECT(n, t) \ 88 | *((ui ## t**)luaL_checkudata(L, n, "libui.user." #t )) 89 | 90 | /* general libui callback mechanism to lua */ 91 | static void create_callback_data(lua_State *L, int n, const char *event) 92 | { 93 | /* Push registery key: userdata pointer to control */ 94 | void *control = UI_CHECK_OBJECT(1, Control); 95 | lua_pushlightuserdata(L, control); 96 | lua_rawget(L, LUA_REGISTRYINDEX); 97 | if (lua_isnil(L, -1)) 98 | { 99 | lua_pop(L, 1); 100 | lua_pushlightuserdata(L, control); 101 | lua_newtable(L); 102 | lua_rawset(L, LUA_REGISTRYINDEX); 103 | lua_pushlightuserdata(L, control); 104 | lua_rawget(L, LUA_REGISTRYINDEX); 105 | } 106 | /* Create table with event/callback data */ 107 | 108 | lua_pushstring(L, event); 109 | lua_newtable(L); 110 | 111 | lua_pushvalue(L, n); 112 | lua_setfield(L, -2, "udata"); 113 | lua_pushvalue(L, 2); 114 | lua_setfield(L, -2, "fn"); 115 | lua_pushvalue(L, 3); 116 | lua_setfield(L, -2, "data"); 117 | 118 | lua_rawset(L, -3); 119 | /* Store in registry */ 120 | lua_pop(L, 1); 121 | } 122 | 123 | static int traceback(lua_State *L) 124 | { 125 | if (!lua_isstring(L, 1)) /* 'message' not a string? */ 126 | return 1; /* keep it intact */ 127 | lua_pushglobaltable(L); 128 | lua_getfield(L, -1, "debug"); 129 | lua_remove(L, -2); 130 | if (!lua_istable(L, -1)) 131 | { 132 | lua_pop(L, 1); 133 | return 1; 134 | } 135 | lua_getfield(L, -1, "traceback"); 136 | if (!lua_isfunction(L, -1)) 137 | { 138 | lua_pop(L, 2); 139 | return 1; 140 | } 141 | lua_pushvalue(L, 1); /* pass error message */ 142 | lua_pushinteger(L, 2); /* skip this function and traceback */ 143 | lua_call(L, 2, 1); /* call debug.traceback */ 144 | return 1; 145 | } 146 | 147 | static int callback(lua_State *L, void *control, const char *event) 148 | { 149 | int ret = 0; 150 | int err = 0; 151 | 152 | /* Get the traceback function in case of error ,+1 */ 153 | lua_pushcfunction(L, traceback); 154 | err = lua_gettop(L); 155 | /* Find table with callback data in registry , +1 */ 156 | lua_pushlightuserdata(L, control); 157 | lua_rawget(L, LUA_REGISTRYINDEX); 158 | luaL_checktype(L, -1, LUA_TTABLE); 159 | 160 | /* Find table with event, +1 */ 161 | lua_pushstring(L, event); 162 | lua_rawget(L, -2); 163 | luaL_checktype(L, -1, LUA_TTABLE); 164 | 165 | /* Get function, control userdata and callback data, +3 */ 166 | lua_getfield(L, -1, "fn"); 167 | luaL_checktype(L, -1, LUA_TFUNCTION); 168 | lua_getfield(L, -2, "udata"); 169 | luaL_checktype(L, -1, LUA_TUSERDATA); 170 | lua_getfield(L, -3, "data"); 171 | 172 | /* Call function */ 173 | if (lua_pcall(L, 2, 1, err)) 174 | { 175 | luaL_error(L, "InnerException: %s", lua_tostring(L, -1)); 176 | lua_pop(L, 1); 177 | } 178 | else 179 | { 180 | if (lua_isboolean(L, -1)) 181 | ret = lua_toboolean(L, -1); 182 | else if (!lua_isnoneornil(L, -1)) 183 | ret = luaL_checkinteger(L, -1); 184 | lua_pop(L, 1); 185 | } 186 | 187 | /* Remove table with given event */ 188 | /* Remove table with callback data in registry */ 189 | /* Remove the traceback function */ 190 | lua_pop(L, 3); 191 | return ret; 192 | } 193 | 194 | /* all ui Control should not be gc, we need destroy it manually */ 195 | /* garbage collection for libui object */ 196 | static int l_uigc(lua_State *L) 197 | { 198 | struct wrap *w = lua_touserdata(L, 1); 199 | uiControl *control = NULL, *parent = NULL; 200 | 201 | if(control && w->ref==0 ) 202 | { 203 | /* 204 | * uint32_t s = w->control->TypeSignature; 205 | */ 206 | 207 | control = w->control; 208 | parent = uiControlParent(control); 209 | 210 | if (parent) 211 | { 212 | if (parent->TypeSignature == 0x57696E64) 213 | { 214 | uiWindowSetChild(uiWindow(parent), NULL); 215 | } 216 | if (parent->TypeSignature == 0x47727062) 217 | { 218 | uiGroupSetChild((uiGroup*)uiWindow(parent), NULL); 219 | } 220 | } 221 | 222 | uiControlDestroy(control); 223 | w->control = NULL; 224 | } 225 | return 0; 226 | } 227 | 228 | /* real code */ 229 | 230 | #include "enum.c" 231 | #include "lcontrol.c" 232 | 233 | #include "larea.c" 234 | #include "lattribute.c" 235 | #include "lattributedstr.c" 236 | #include "lbox.c" 237 | #include "lbutton.c" 238 | #include "lcheckbox.c" 239 | #include "lcolorbutton.c" 240 | #include "lcombobox.c" 241 | #include "ldatetimerpicker.c" 242 | #include "ldraw.c" 243 | #include "lentry.c" 244 | #include "lfontbutton.c" 245 | #include "lform.c" 246 | #include "lgrid.c" 247 | #include "lgroup.c" 248 | #include "limage.c" 249 | #include "llabel.c" 250 | #include "lmenu.c" 251 | #include "lmenuitem.c" 252 | #include "lmultiline.c" 253 | #include "lprogressbar.c" 254 | #include "lradiobuttons.c" 255 | #include "lseparator.c" 256 | #include "lslider.c" 257 | #include "lspinbox.c" 258 | #include "ltab.c" 259 | #include "ltable.c" 260 | #include "lwindow.c" 261 | 262 | /* Various top level */ 263 | 264 | static int l_uiInit(lua_State *L) 265 | { 266 | int ret = 1; 267 | uiInitOptions o; 268 | 269 | memset(&o, 0, sizeof(uiInitOptions)); 270 | 271 | const char *err = uiInit(&o); 272 | if (err) 273 | { 274 | lua_pushnil(L); 275 | lua_pushstring(L, err); 276 | uiFreeInitError(err); 277 | ret = 2; 278 | } 279 | else 280 | lua_pushboolean(L, 1); 281 | return ret; 282 | } 283 | 284 | static int l_uiUninit(lua_State *L) 285 | { 286 | uiUninit(); 287 | return 0; 288 | } 289 | 290 | static int l_uiMain(lua_State *L) 291 | { 292 | uiMain(); 293 | return 0; 294 | } 295 | 296 | static int l_uiMainStep(lua_State *L) 297 | { 298 | lua_pushboolean(L, uiMainStep(luaL_checkboolean(L, 1))); 299 | return 1; 300 | } 301 | 302 | static int l_uiMainSteps(lua_State *L) 303 | { 304 | uiMainSteps();; 305 | return 0; 306 | } 307 | 308 | static int l_uiQuit(lua_State *L) 309 | { 310 | uiQuit(); 311 | return 0; 312 | } 313 | 314 | static int l_uiUserBugCannotSetParentOnToplevel(lua_State *L) 315 | { 316 | uiUserBugCannotSetParentOnToplevel(luaL_checkstring(L, 1)); 317 | return 0; 318 | } 319 | 320 | static int l_QueueDumpWriter(lua_State* L, const void* p, size_t sz, void* B) 321 | { 322 | (void)L; 323 | luaL_addlstring((luaL_Buffer*) B, (const char*) p, sz); 324 | return 0; 325 | } 326 | 327 | static const char* l_QueueThreadDump(lua_State* L, int idx, size_t* l) 328 | { 329 | if (lua_isstring(L, idx)) 330 | { 331 | return lua_tolstring(L, idx, l); 332 | } 333 | else 334 | { 335 | const char* buff = NULL; 336 | int top = lua_gettop(L); 337 | luaL_Buffer b; 338 | int test_lua_dump; 339 | luaL_checktype(L, idx, LUA_TFUNCTION); 340 | lua_pushvalue(L, idx); 341 | luaL_buffinit(L, &b); 342 | test_lua_dump = (lua_dump(L, l_QueueDumpWriter, &b, 1) == 0); 343 | if (test_lua_dump) 344 | { 345 | luaL_pushresult(&b); 346 | buff = lua_tolstring(L, -1, l); 347 | } 348 | else 349 | luaL_error(L, "Error: unable to dump given function"); 350 | lua_settop(L, top); 351 | 352 | return buff; 353 | } 354 | } 355 | 356 | typedef struct value_s 357 | { 358 | int type; 359 | union 360 | { 361 | double n; 362 | int i; 363 | struct 364 | { 365 | int l; 366 | char* p; 367 | } s; 368 | void* p; 369 | } v; 370 | } Value; 371 | 372 | #define MAX_ARGS_NUM 9 373 | typedef struct QueueArg_s 374 | { 375 | size_t sz; 376 | char *entry; 377 | lua_State *L; 378 | 379 | size_t argc; 380 | Value argv[MAX_ARGS_NUM]; 381 | } QueueArg; 382 | 383 | // This must in main thread 384 | static void l_QueueMain(void *data) 385 | { 386 | int i; 387 | int top = 0; 388 | QueueArg *arg = (QueueArg*)data; 389 | lua_State *L = arg->L; 390 | 391 | top = lua_gettop(L); 392 | lua_pushcfunction(L, traceback); 393 | luaL_loadbuffer(L, arg->entry, arg->sz, "=queue"); 394 | luaL_checktype(L, -1, LUA_TFUNCTION); 395 | 396 | for(i=0; iargc; i++) 397 | { 398 | Value *val = arg->argv+i; 399 | switch(val->type) 400 | { 401 | case LUA_TBOOLEAN: 402 | lua_pushboolean(L, val->v.i); 403 | break; 404 | case LUA_TNUMBER: 405 | lua_pushnumber(L, val->v.n); 406 | break; 407 | case LUA_TSTRING: 408 | lua_pushlstring(L, val->v.s.p, val->v.s.l); 409 | break; 410 | case LUA_TNIL: 411 | lua_pushnil(L); 412 | break; 413 | } 414 | } 415 | 416 | if (lua_pcall(L, arg->argc, 0, top+1)) 417 | { 418 | luaL_error(L, lua_tostring(L, -1)); 419 | lua_pop(L, 1); 420 | } 421 | /* remove traceback function*/ 422 | lua_pop(L, 1); 423 | luaL_argcheck(L, top == lua_gettop(L), 1, "stack not balance"); 424 | } 425 | 426 | static int l_uiQueueMain(lua_State *L) 427 | { 428 | int i, top; 429 | QueueArg *arg = NULL; 430 | size_t sz; 431 | const char* p; 432 | 433 | // check main thread exist 434 | if (_main_L==NULL) 435 | { 436 | luaL_error(L, "Can't access main thread"); 437 | return 0; 438 | } 439 | 440 | top = lua_gettop(L); 441 | luaL_checktype(L, 1, LUA_TFUNCTION); 442 | arg = malloc(sizeof(QueueArg)); 443 | memset(arg, 0, sizeof(QueueArg)); 444 | 445 | p = l_QueueThreadDump(L, 1, &sz); 446 | arg->entry = malloc(sz+1); 447 | memcpy(arg->entry, p, sz); 448 | arg->entry[sz] = '\0'; 449 | arg->sz = sz; 450 | arg->L = _main_L; 451 | 452 | arg->argc = (top-1 > MAX_ARGS_NUM) ? MAX_ARGS_NUM : top - 1; 453 | for(i=0; i < arg->argc; i++) 454 | { 455 | int type = lua_type(L, i+2); 456 | Value *val = arg->argv+i; 457 | val->type = type; 458 | 459 | luaL_argcheck(L, type==LUA_TBOOLEAN || type==LUA_TNUMBER || 460 | type==LUA_TSTRING || type==LUA_TNIL, 461 | i+2, 462 | "only accpet nil, boolean, number or string value"); 463 | 464 | if (val->type==LUA_TBOOLEAN) 465 | { 466 | val->v.i = lua_toboolean(L, i+2); 467 | } 468 | else if(val->type==LUA_TNUMBER) 469 | { 470 | val->v.n = lua_tonumber(L, i+2); 471 | val->type = LUA_TNUMBER; 472 | } 473 | else if(val->type==LUA_TSTRING) 474 | { 475 | p = lua_tolstring(L,i+2, &sz); 476 | val->v.s.l = sz; 477 | val->v.s.p = malloc(sz); 478 | memcpy(val->v.s.p, p, sz); 479 | } 480 | else 481 | val->type = LUA_TNIL; 482 | } 483 | 484 | uiQueueMain(l_QueueMain, arg); 485 | return 0; 486 | } 487 | 488 | static int on_ShouldQuit(void *data) 489 | { 490 | int ret = 0; 491 | int err = 0; 492 | lua_State *L = data; 493 | 494 | /* Get the traceback function in case of error */ 495 | lua_pushcfunction(L, traceback); 496 | err = lua_gettop(L); 497 | /* Find table with callback data in registry */ 498 | lua_pushlightuserdata(L, (void*)on_ShouldQuit); 499 | lua_gettable(L, LUA_REGISTRYINDEX); 500 | 501 | /* Get function, control userdata and callback data */ 502 | luaL_checktype(L, -1, LUA_TTABLE); 503 | lua_getfield(L, -1, "fn"); 504 | luaL_checktype(L, -1, LUA_TFUNCTION); 505 | lua_getfield(L, -2, "data"); 506 | 507 | /* Call function */ 508 | if (lua_pcall(L, 1, 1, err)) 509 | { 510 | luaL_error(L, lua_tostring(L, -1)); 511 | lua_pop(L, 1); 512 | } 513 | else 514 | { 515 | if (lua_isboolean(L, -1)) 516 | ret = lua_toboolean(L, -1); 517 | else if (!lua_isnoneornil(L, -1)) 518 | ret = luaL_checkinteger(L, -1); 519 | lua_pop(L, 1); 520 | } 521 | 522 | /* Remove table with callback data in registry */ 523 | lua_pop(L, 1); 524 | /* Remove the traceback function */ 525 | lua_pop(L, 1); 526 | return ret; 527 | } 528 | 529 | static int l_uiOnShouldQuit(lua_State *L) 530 | { 531 | uiOnShouldQuit(on_ShouldQuit, L); 532 | 533 | /* Push registery key: userdata pointer to control */ 534 | lua_pushlightuserdata(L, (void*)on_ShouldQuit); 535 | lua_newtable(L); 536 | lua_pushvalue(L, 1); 537 | lua_setfield(L, -2, "fn"); 538 | lua_pushvalue(L, 2); 539 | lua_setfield(L, -2, "data"); 540 | 541 | /* Store in registry */ 542 | lua_settable(L, LUA_REGISTRYINDEX); 543 | return 0; 544 | } 545 | 546 | static int l_timer_cb(void *data); 547 | static int l_uiTimer(lua_State *L); 548 | 549 | static int l_timer_cb(void *data) 550 | { 551 | int status = 0; 552 | lua_State *L = (lua_State*)data; 553 | 554 | lua_pushlightuserdata(L, (void*)l_uiTimer); 555 | lua_rawget(L, LUA_REGISTRYINDEX); 556 | lua_pushlightuserdata(L, (void*)l_timer_cb); 557 | lua_rawget(L, LUA_REGISTRYINDEX); 558 | 559 | status = lua_pcall(L, 1, 1, 0); 560 | if(status==0) 561 | { 562 | if (lua_isnumber(L, -1)) 563 | status = lua_tointeger(L, -1); 564 | else 565 | status = lua_toboolean(L, -1); 566 | lua_pop(L, 1); 567 | } 568 | else 569 | { 570 | lua_pushfstring(L, "uiTimer callback fail: %s", lua_tostring(L, -1)); 571 | lua_remove(L, -2); 572 | lua_error(L); 573 | } 574 | return status; 575 | } 576 | 577 | static int l_uiTimer(lua_State *L) 578 | { 579 | int milliseconds = luaL_checkinteger(L, 1); 580 | luaL_checktype(L, 2, LUA_TFUNCTION); 581 | if(lua_isnone(L, 3)) 582 | lua_pushnil(L); 583 | 584 | lua_pushlightuserdata(L, (void*)l_uiTimer); 585 | lua_pushvalue(L, 2); 586 | lua_rawset(L, LUA_REGISTRYINDEX); 587 | 588 | lua_pushlightuserdata(L, (void*)l_timer_cb); 589 | lua_pushvalue(L, 3); 590 | lua_rawset(L, LUA_REGISTRYINDEX); 591 | 592 | uiTimer(milliseconds, l_timer_cb, L); 593 | return 0; 594 | } 595 | 596 | static struct luaL_Reg lui_table[] = 597 | { 598 | 599 | { "Init", l_uiInit }, 600 | { "Uninit", l_uiUninit }, 601 | { "Main", l_uiMain }, 602 | { "MainStep", l_uiMainStep }, 603 | { "MainSteps", l_uiMainSteps }, 604 | { "Quit", l_uiQuit }, 605 | { "QueueMain", l_uiQueueMain }, 606 | { "OnShouldQuit", l_uiOnShouldQuit }, 607 | { 608 | "UserBugCannotSetParentOnTopLevel", 609 | l_uiUserBugCannotSetParentOnToplevel 610 | }, 611 | 612 | { "Timer", l_uiTimer }, 613 | 614 | { "OpenFile", l_uiOpenFile }, 615 | { "SaveFile", l_uiSaveFile }, 616 | { "MsgBox", l_uiMsgBox }, 617 | { "MsgBoxError", l_uiMsgBoxError }, 618 | 619 | { "NewArea", l_uiNewArea }, 620 | { "NewAttribute", l_uiNewAttribute }, 621 | { "NewAttributedString", l_uiNewAttributedString }, 622 | { "NewButton", l_uiNewButton }, 623 | { "NewCheckbox", l_uiNewCheckbox }, 624 | { "NewCombobox", l_uiNewCombobox }, 625 | { "NewColorButton", l_uiNewColorButton }, 626 | { "NewDateTimePicker", l_uiNewDateTimePicker }, 627 | { "NewDatePicker", l_uiNewDatePicker }, 628 | { "NewEditableCombobox", l_uiNewEditableCombobox }, 629 | { "NewEntry", l_uiNewEntry }, 630 | { "NewFontButton", l_uiNewFontButton }, 631 | { "NewForm", l_uiNewForm }, 632 | { "NewGrid", l_uiNewGrid }, 633 | { "NewGroup", l_uiNewGroup }, 634 | { "NewHorizontalBox", l_uiNewHorizontalBox }, 635 | { "NewHorizontalSeparator", l_uiNewHorizontalSeparator }, 636 | { "NewImage", l_uiNewImage }, 637 | { "NewLabel", l_uiNewLabel }, 638 | { "NewMenu", l_uiNewMenu }, 639 | { "NewMultilineEntry", l_uiNewMultilineEntry }, 640 | { 641 | "NewNonWrappingMultilineEntry", 642 | l_uiNewNonWrappingMultilineEntry 643 | }, 644 | { "NewOpenTypeFeatures", l_uiNewOpenTypeFeatures }, 645 | { "NewPasswordEntry", l_uiNewPasswordEntry }, 646 | { "NewProgressBar", l_uiNewProgressBar }, 647 | { "NewRadioButtons", l_uiNewRadioButtons }, 648 | { "NewSearchEntry", l_uiNewSearchEntry }, 649 | { "NewSlider", l_uiNewSlider }, 650 | { "NewSpinbox", l_uiNewSpinbox }, 651 | { "NewTimePicker", l_uiNewTimePicker }, 652 | { "NewTab", l_uiNewTab }, 653 | { "NewTable", l_uiNewTable }, 654 | { "NewTableValue", l_uiTableValueNew }, 655 | { "NewTableModelHandler", l_uiNewTableModelHandler }, 656 | { 657 | "NewTableTextColumnOptionalParams", 658 | l_uiNewTableTextColumnOptionalParams 659 | }, 660 | { "NewVerticalBox", l_uiNewVerticalBox }, 661 | { "NewVerticalSeparator", l_uiNewVerticalSeparator }, 662 | { "NewWindow", l_uiNewWindow }, 663 | 664 | { "NewFontDescriptor", l_uiNewFontDescriptor}, 665 | 666 | { "DrawNewAreaHandler", l_uiDrawNewAreaHandler }, 667 | { "DrawNewBrush", l_uiDrawNewBrush }, 668 | { "DrawNewPath", l_uiDrawNewPath }, 669 | { "DrawNewMatrix", l_uiDrawNewMatrix }, 670 | { "DrawNewStrokeParams", l_uiDrawNewStrokeParams }, 671 | { "DrawNewTextLayout", l_uiDrawNewTextLayout }, 672 | { "DrawNewTextLayoutParams",l_uiDrawNewTextLayoutParams }, 673 | 674 | { NULL, NULL } 675 | }; 676 | 677 | LUA_API int luaopen_lui(lua_State *L) 678 | { 679 | UI_CREATE_META(Control) 680 | 681 | UI_CREATE_META(Area) 682 | UI_SET_GROUP(Area, Control); 683 | UI_CREATE_META(Box) 684 | UI_SET_GROUP(Box, Control); 685 | UI_CREATE_META(Button) 686 | UI_SET_GROUP(Button, Control); 687 | UI_CREATE_META(Checkbox) 688 | UI_SET_GROUP(Checkbox, Control); 689 | UI_CREATE_META(Combobox) 690 | UI_SET_GROUP(Combobox, Control); 691 | UI_CREATE_META(ColorButton) 692 | UI_SET_GROUP(ColorButton, Control); 693 | UI_CREATE_META(DateTimePicker) 694 | UI_SET_GROUP(DateTimePicker, Control); 695 | UI_CREATE_META(EditableCombobox) 696 | UI_SET_GROUP(EditableCombobox, Control); 697 | UI_CREATE_META(Entry) 698 | UI_SET_GROUP(Entry, Control); 699 | UI_CREATE_META(FontButton) 700 | UI_SET_GROUP(FontButton, Control); 701 | UI_CREATE_META(Form) 702 | UI_SET_GROUP(Form, Control); 703 | UI_CREATE_META(Grid) 704 | UI_SET_GROUP(Grid, Control); 705 | UI_CREATE_META(Group) 706 | UI_SET_GROUP(Group, Control); 707 | UI_CREATE_META(Image) 708 | UI_SET_GROUP(Image, Control); 709 | UI_CREATE_META(Label) 710 | UI_SET_GROUP(Label, Control); 711 | UI_CREATE_META(MenuItem) 712 | UI_SET_GROUP(MenuItem, Control); 713 | UI_CREATE_META(Menu) 714 | UI_SET_GROUP(Menu, Control); 715 | UI_CREATE_META(MultilineEntry) 716 | UI_SET_GROUP(MultilineEntry, Control); 717 | UI_CREATE_META(ProgressBar) 718 | UI_SET_GROUP(ProgressBar, Control); 719 | UI_CREATE_META(RadioButtons) 720 | UI_SET_GROUP(RadioButtons, Control); 721 | UI_CREATE_META(Separator) 722 | UI_SET_GROUP(Separator, Control); 723 | UI_CREATE_META(Slider) 724 | UI_SET_GROUP(Slider, Control); 725 | UI_CREATE_META(Spinbox) 726 | UI_SET_GROUP(Spinbox, Control); 727 | UI_CREATE_META(Tab) 728 | UI_SET_GROUP(Tab, Control); 729 | UI_CREATE_META(Table) 730 | UI_SET_GROUP(Table, Control); 731 | UI_CREATE_META(Window) 732 | UI_SET_GROUP(Window, Control); 733 | 734 | CREATE_USER_META(Attribute) 735 | CREATE_USER_META(AttributedString) 736 | CREATE_USER_META(FontDescriptor) 737 | CREATE_USER_META(OpenTypeFeatures) 738 | CREATE_USER_META(TableModel) 739 | CREATE_USER_META(TableModelHandler) 740 | CREATE_USER_META(TableValue) 741 | CREATE_USER_META(TableParams) 742 | 743 | /* draw, not finished */ 744 | CREATE_DRAWMETA 745 | 746 | luaL_newlib(L, lui_table); 747 | l_REG_UI_ENUM(L, lua_gettop(L)); 748 | 749 | // store as a global variable, to support multi-thread 750 | if (_main_L==NULL) 751 | _main_L = L; 752 | 753 | return 1; 754 | } 755 | -------------------------------------------------------------------------------- /src/lui.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "ui.h" 10 | 11 | /* make lua version compat */ 12 | #if LUA_VERSION_NUM < 503 13 | # include "c-api/compat-5.3.h" 14 | #endif 15 | #include "auxiliar.h" 16 | 17 | -------------------------------------------------------------------------------- /src/lwindow.c: -------------------------------------------------------------------------------- 1 | static int onClosing(uiWindow *w, void *data) 2 | { 3 | uiQuit(); 4 | return 1; 5 | } 6 | 7 | static int l_uiNewWindow(lua_State *L) 8 | { 9 | uiWindow *win = uiNewWindow( 10 | luaL_checkstring(L, 1), 11 | luaL_checkinteger(L, 2), 12 | luaL_checkinteger(L, 3), 13 | luaL_checkboolean(L, 4) 14 | ); 15 | uiWindowOnClosing(win, onClosing, NULL); 16 | UI_CREATE_OBJECT(Window, win); 17 | return 1; 18 | } 19 | 20 | static int l_uiWindowTitle(lua_State *L) 21 | { 22 | if (lua_isnone(L, 2)) 23 | { 24 | lua_pushstring(L, uiWindowTitle(UI_CHECK_OBJECT(1, Window))); 25 | return 1; 26 | } 27 | uiWindowSetTitle(UI_CHECK_OBJECT(1, Window), luaL_checkstring(L, 2)); 28 | UI_RETURN_SELF; 29 | } 30 | 31 | static int l_uiWindowContentSize(lua_State *L) 32 | { 33 | int width, height; 34 | if (lua_isnone(L, 2)) 35 | { 36 | uiWindowContentSize(UI_CHECK_OBJECT(1, Window), &width, &height); 37 | lua_pushinteger(L, width); 38 | lua_pushinteger(L, height); 39 | return 2; 40 | } 41 | width = luaL_checkinteger(L, 2); 42 | height = luaL_checkinteger(L, 3); 43 | uiWindowSetContentSize(UI_CHECK_OBJECT(1, Window), width, height); 44 | UI_RETURN_SELF; 45 | } 46 | 47 | static int l_uiWindowFullscreen(lua_State *L) 48 | { 49 | if (lua_isnone(L, 2)) 50 | { 51 | lua_pushboolean(L, uiWindowFullscreen(UI_CHECK_OBJECT(1, Window))); 52 | return 1; 53 | } 54 | uiWindowSetFullscreen(UI_CHECK_OBJECT(1, Window), luaL_checkboolean(L, 2)); 55 | UI_RETURN_SELF; 56 | } 57 | 58 | static void Window_On_ContentSizeChanged(uiWindow *b, void *data) 59 | { 60 | callback(data, b, "contentsizechanged"); 61 | } 62 | 63 | static int l_uiWindowOnContentSizeChanged(lua_State *L) 64 | { 65 | uiWindowOnContentSizeChanged(UI_CHECK_OBJECT(1, Window), Window_On_ContentSizeChanged, L); 66 | create_callback_data(L, 1, "contentsizechanged"); 67 | UI_RETURN_SELF; 68 | } 69 | 70 | static int Window_On_Closing(uiWindow *b, void *data) 71 | { 72 | return callback(data, b, "closing"); 73 | } 74 | 75 | static int l_uiWindowOnClosing(lua_State *L) 76 | { 77 | uiWindowOnClosing(UI_CHECK_OBJECT(1, Window), Window_On_Closing, L); 78 | create_callback_data(L, 1, "closing"); 79 | UI_RETURN_SELF; 80 | } 81 | 82 | static int l_uiWindowBorderless(lua_State *L) 83 | { 84 | if (lua_isnone(L, 2)) 85 | { 86 | lua_pushboolean(L, uiWindowBorderless(UI_CHECK_OBJECT(1, Window))); 87 | return 1; 88 | } 89 | uiWindowSetBorderless(UI_CHECK_OBJECT(1, Window), luaL_checkboolean(L, 2)); 90 | UI_RETURN_SELF; 91 | } 92 | 93 | static int l_uiWindowSetChild(lua_State *L) 94 | { 95 | uiWindowSetChild(UI_CHECK_OBJECT(1, Window), UI_CHECK_OBJECT(2, Control)); 96 | lua_getmetatable(L, 1); 97 | lua_pushvalue(L, 2); 98 | lua_pushboolean(L, 1); 99 | lua_settable(L, -3); 100 | UI_RETURN_SELF; 101 | } 102 | 103 | static int l_uiWindowMargined(lua_State *L) 104 | { 105 | if (lua_isnone(L, 2)) 106 | { 107 | lua_pushboolean(L, uiWindowMargined(UI_CHECK_OBJECT(1, Window))); 108 | return 1; 109 | } 110 | uiWindowSetMargined(UI_CHECK_OBJECT(1, Window), luaL_checkboolean(L, 2)); 111 | UI_RETURN_SELF; 112 | } 113 | 114 | static int l_uiOpenFile(lua_State* L) 115 | { 116 | char* f = uiOpenFile(UI_CHECK_OBJECT(1, Window)); 117 | if (f) 118 | { 119 | lua_pushstring(L, f); 120 | uiFreeText(f); 121 | } 122 | else 123 | { 124 | lua_pushnil(L); 125 | } 126 | return 1; 127 | } 128 | 129 | static int l_uiSaveFile(lua_State* L) 130 | { 131 | char* f = uiSaveFile(UI_CHECK_OBJECT(1, Window)); 132 | if (f) 133 | { 134 | lua_pushstring(L, f); 135 | uiFreeText(f); 136 | } 137 | else 138 | { 139 | lua_pushnil(L); 140 | } 141 | return 1; 142 | } 143 | 144 | static int l_uiMsgBox(lua_State* L) 145 | { 146 | uiMsgBox(UI_CHECK_OBJECT(1, Window), luaL_checkstring(L, 2), luaL_checkstring(L, 3)); 147 | return 0; 148 | } 149 | 150 | static int l_uiMsgBoxError(lua_State* L) 151 | { 152 | uiMsgBoxError(UI_CHECK_OBJECT(1, Window), luaL_checkstring(L, 2), luaL_checkstring(L, 3)); 153 | return 0; 154 | } 155 | 156 | static struct luaL_Reg meta_Window[] = 157 | { 158 | { "Title", l_uiWindowTitle }, 159 | { "ContentSize", l_uiWindowContentSize }, 160 | { "Fullscreen", l_uiWindowFullscreen }, 161 | { "OnContentSizeChanged", l_uiWindowOnContentSizeChanged }, 162 | { "OnClosing", l_uiWindowOnClosing }, 163 | { "Borderless", l_uiWindowBorderless }, 164 | { "SetChild", l_uiWindowSetChild }, 165 | { "Margined", l_uiWindowMargined }, 166 | 167 | { "OpenFile", l_uiOpenFile }, 168 | { "SaveFile", l_uiSaveFile }, 169 | { "MsgBox", l_uiMsgBox }, 170 | { "MsgBoxError", l_uiMsgBoxError }, 171 | 172 | CONTROL_COMMON_METAFIELD 173 | { NULL, NULL } 174 | }; 175 | -------------------------------------------------------------------------------- /test.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/lua 2 | 3 | local ui = require "lui" 4 | local steps = true 5 | ui.Init() 6 | 7 | i = 0 8 | ui.Timer(1000, function(i) 9 | print(i, os.date()) 10 | return 1 11 | end, i) 12 | 13 | local spinbox, slider, progressbar 14 | 15 | local function update(control) 16 | local v = control:Value() 17 | spinbox:Value(v) 18 | slider:Value(v) 19 | progressbar:Value(v) 20 | end 21 | 22 | spinbox = ui.NewSpinbox(0, 100):OnChanged(update) 23 | slider = ui.NewSlider(0, 100):OnChanged(update) 24 | progressbar = ui.NewProgressBar(0, 100) 25 | 26 | local win = ui.NewWindow("Hello", 320, 200, false):Margined(true):SetChild( 27 | ui.NewVerticalBox():Append( 28 | ui.NewHorizontalBox():Append( 29 | ui.NewGroup("Basic Controls"):Margined(true):SetChild( 30 | ui.NewVerticalBox():Padded(true):Append( 31 | ui.NewButton("Button"), ui.NewCheckbox("Checkbox"), 32 | ui.NewLabel("Label"), ui.NewHorizontalSeparator(), 33 | ui.NewDatePicker(), ui.NewDateTimePicker(), 34 | ui.NewTimePicker())), 35 | ui.NewVerticalBox():Append( 36 | ui.NewGroup("Numbers"):Margined(true):SetChild( 37 | ui.NewVerticalBox():Padded(true):Append(spinbox, slider, 38 | progressbar))) 39 | :Append(ui.NewGroup("Lists"):Margined(true):SetChild( 40 | ui.NewVerticalBox():Padded(true):Append( 41 | ui.NewCombobox():Append("Combobox Item 1", 42 | "Combobox Item 2", 43 | "Combobox Item 3"), 44 | ui.NewEditableCombobox():Append( 45 | "Editable Item 1", "Editable Item 2", 46 | "Editable Item 3"), 47 | ui.NewRadioButtons():Append("Radio Button 1", 48 | "Radio Button 2", 49 | "Radio Button 3")) 50 | :Append(ui.NewTab():Append("Page 1", 51 | ui.NewHorizontalBox(), 52 | "Page 2", 53 | ui.NewHorizontalBox(), 54 | "Page 3", 55 | ui.NewHorizontalBox()), 56 | true)), true), true), true)) 57 | 58 | win:Show() 59 | 60 | ui.QueueMain(function(a, b, c, d, e) 61 | assert(a == 1) 62 | assert(b == nil) 63 | assert(c == 'a') 64 | assert(d == true) 65 | assert(e == nil) 66 | print('QueueMain OK') 67 | end, 1, nil, 'a', true) 68 | 69 | if (not steps) then 70 | ui.Main() 71 | else 72 | ui.MainSteps() 73 | while ui.MainStep(true) do end 74 | end 75 | --------------------------------------------------------------------------------