1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
|
-- This file is executed with the "iup" table already as the globalindex
------------------------------------------------------------------------------
-- Callback handler
------------------------------------------------------------------------------
callbacks = {}
function iupCallMethod(name, ...)
local handle = ... -- always the handle
local func = handle[name]
if (not func) then
return
end
if type(func) == "function" then
return func(...)
elseif type(func) == "string" then
local temp = self
self = handle
local result = iup.dostring(func)
self = temp
return result
else
return iup.ERROR
end
end
function RegisterCallback(name, func, type)
if not callbacks[name] then callbacks[name] = {} end
local cb = callbacks[name]
if type then
cb[type] = func
else
cb[1] = func
end
end
------------------------------------------------------------------------------
-- Meta Methods
------------------------------------------------------------------------------
local widget_gettable = function(object, index)
local p = object
local v
while 1 do
v = rawget(p, index)
if v then return v end
p = rawget(p, "parent")
if not p then return nil end
end
end
iupNewClass("iup widget")
iupSetMethod("iup widget", "__index", widget_gettable)
local ihandle_gettable = function(handle, index)
local INDEX = string.upper(index)
if (callbacks[INDEX]) then
local object = iupGetWidget(handle)
if (not object or type(object)~="table") then error("invalid iup handle") end
return object[index]
else
local value = GetAttribute(handle, INDEX)
if (not value) then
local object = iupGetWidget(handle)
if (not object or type(object)~="table") then error("invalid iup handle") end
return object[index]
elseif type(value)== "number" or type(value) == "string" then
local ih = GetHandle(value)
if ih then return ih
else return value end
else
return value
end
end
end
local ihandle_settable = function(handle, index, value)
local ti = type(index)
local tv = type(value)
local object = iupGetWidget(handle)
if (not object or type(object)~="table") then error("invalid iup handle") end
if ti == "number" or ti == "string" then -- check if a valid C name
local INDEX = string.upper(index)
local cb = callbacks[INDEX]
if (cb) then -- if a callback name
local func = cb[1]
if (not func) then
func = cb[GetClassName(handle)]
end
iupSetCallback(handle, INDEX, func, value) -- register the pre-defined C callback
object[index] = value -- store also in Lua
elseif iupGetClass(value) == "iup handle" then -- if a iup handle
local name = ihandle_setname(value)
SetAttribute(handle, INDEX, name)
object[index] = nil -- if there was something in Lua remove it
elseif tv == "string" or tv == "number" or tv == "nil" then -- if a common value
SetAttribute(handle, INDEX, value)
object[index] = nil -- if there was something in Lua remove it
else
object[index] = value -- store also in Lua
end
else
object[index] = value -- store also in Lua
end
end
iupNewClass("iup handle")
iupSetMethod("iup handle", "__index", ihandle_gettable)
iupSetMethod("iup handle", "__newindex", ihandle_settable)
iupSetMethod("iup handle", "__tostring", ihandle_tostring)
iupSetMethod("iup handle", "__eq", ihandle_compare) -- implemented in C
------------------------------------------------------------------------------
-- Utilities
------------------------------------------------------------------------------
function ihandle_setname(v) -- used also by radio and zbox
local name = GetName(v)
if not name then
local autoname = string.format("_IUPLUA_NAME(%s)", tostring(v))
SetHandle(autoname, v)
return autoname
end
return name
end
function iupRegisterWidget(ctrl) -- called by all the controls initialization functions
iup[ctrl.nick] = function(arg)
return ctrl:constructor(arg)
end
end
function RegisterHandle(handle, typename)
iupSetClass(handle, "iup handle")
local object = iupGetWidget(handle)
if not object then
local class = iup[string.upper(typename)]
if not class then
class = WIDGET
end
local object = { parent=class, handle=handle }
iupSetClass(object, "iup widget")
iupSetWidget(handle, object)
end
return handle
end
------------------------------------------------------------------------------
-- Widget class (top class)
------------------------------------------------------------------------------
WIDGET = {
callback = {}
}
function WIDGET.show(object)
Show(object.handle)
end
function WIDGET.hide(object)
Hide(object.handle)
end
function WIDGET.map(object)
Map(object.handle)
end
function WIDGET.constructor(class, arg)
local handle = class:createElement(arg)
local object = {
parent = class,
handle = handle
}
iupSetClass(handle, "iup handle")
iupSetClass(object, "iup widget")
iupSetWidget(handle, object)
object:setAttributes(arg)
return handle
end
function WIDGET.setAttributes(object, arg)
local handle = object.handle
for i,v in pairs(arg) do
if type(i) == "number" and iupGetClass(v) == "iup handle" then
-- We should not set this or other elements (such as iuptext)
-- will erroneosly inherit it
rawset(object, i, v)
else
-- this will call settable metamethod
handle[i] = v
end
end
end
-- all the objects in the hierarchy must be "iup widget"
-- Must repeat this call for every new widget
iupSetClass(WIDGET, "iup widget")
------------------------------------------------------------------------------
-- Box class (inherits from WIDGET)
------------------------------------------------------------------------------
BOX = {
parent = WIDGET
}
function BOX.setAttributes(object, arg)
local handle = rawget(object, "handle")
local n = #arg
for i = 1, n do
if iupGetClass(arg[i]) == "iup handle" then
Append(handle, arg[i])
end
end
WIDGET.setAttributes(object, arg)
end
iupSetClass(BOX, "iup widget")
------------------------------------------------------------------------------
-- Compatibility functions.
------------------------------------------------------------------------------
error_message_popup = nil
function _ERRORMESSAGE(err,traceback)
err = err..(traceback or "")
if (error_message_popup) then
error_message_popup.value = err
else
local bt = button{title="Ok", size="60", action="error_message_popup = nil; return iup.CLOSE"}
local ml = multiline{expand="YES", readonly="YES", value=err, size="300x150"}
local vb = vbox{ml, bt; alignment="ACENTER", margin="10x10", gap="10"}
local dg = dialog{vb; title="Error Message",defaultesc=bt,defaultenter=bt,startfocus=bt}
error_message_popup = ml
dg:popup(CENTER, CENTER)
dg:destroy()
error_message_popup = nil
end
end
pack = function (...) return {...} end
function protectedcall_(f, err)
if not f then
_ERRORMESSAGE(err)
return
end
local ret = pack(pcall(f))
if not ret[1] then
_ERRORMESSAGE(ret[2])
return
else
table.remove(ret, 1)
return unpack(ret)
end
end
function dostring(s) return protectedcall_(loadstring(s)) end
function dofile(f) return protectedcall_(loadfile(f)) end
function RGB(r, g, b)
return string.format("%d %d %d", 255*r, 255*g, 255*b)
end
-- This will allow both names to be used in the same application
-- also will allow static linking to work with require
if _G.package then
_G.package.loaded["iuplua"] = iup
_G.package.loaded["iuplua51"] = iup
iup._M = iup
iup._PACKAGE = "iuplua"
end
|