diff options
Diffstat (limited to '')
-rw-r--r-- | ClientHamr/GuiLua/skang.lua | 307 |
1 files changed, 170 insertions, 137 deletions
diff --git a/ClientHamr/GuiLua/skang.lua b/ClientHamr/GuiLua/skang.lua index 9a67231..b36b8a3 100644 --- a/ClientHamr/GuiLua/skang.lua +++ b/ClientHamr/GuiLua/skang.lua | |||
@@ -237,65 +237,15 @@ isBoolean = function (aBoolean) | |||
237 | end | 237 | end |
238 | 238 | ||
239 | 239 | ||
240 | --[[ Stuff package | 240 | --[[ Thing Java package |
241 | 241 | ||
242 | In matrix-RAD Stuff took care of multi value Things, like database rows. | 242 | matrix-RAD had Thing as the base class of everything. |
243 | |||
244 | Stuff is an abstract class that gets extended by other classes, like | ||
245 | SquealStuff, which was the only thing extending it. It dealt with the | ||
246 | basic "collection of things" stuff. Each individual thing was called a | ||
247 | stufflet. A final fooStuff would extend SquealStuff, and include an | ||
248 | array of strings called "stufflets" that at least named the stufflets, | ||
249 | but could also include metadata and links to other Stuffs. | ||
250 | |||
251 | There was various infrastructure for reading and writing Stuff, throwing | ||
252 | rows of Stuff into grids, having choices of Stuff, linking stufflets to | ||
253 | individual widgets, having default Stuffs for windows, validating | ||
254 | Stuffs, etc. | ||
255 | |||
256 | In Lua, setting up stuff has been folded into the general Thing stuff. | ||
257 | |||
258 | ]] | ||
259 | |||
260 | |||
261 | --[[ Thing package | ||
262 | |||
263 | matrix-RAD had Thing as the base class of everything. Lua doesn't have | ||
264 | inheritance as such, but an inheritance structure can be built using | ||
265 | Lua's meta language capabilities. I think we still need this sort of | ||
266 | thing. Java inheritance and interfaces where used. There's quite a few | ||
267 | variations of OO support has been written for Lua, maybe some of that | ||
268 | could be used? http://lua-users.org/wiki/ObjectOrientedProgramming | ||
269 | |||
270 | Other useful links - | ||
271 | |||
272 | http://lua-users.org/wiki/ClassesViaModules (not in the above for some reason. | ||
273 | http://lua-users.org/wiki/MetamethodsTutorial | ||
274 | http://lua-users.org/wiki/MetatableEvents | ||
275 | |||
276 | http://lua-users.org/wiki/MechanismNotPolicy | ||
277 | http://www.inf.puc-rio.br/~roberto/pil2/chapter15.pdf | ||
278 | http://lua-users.org/lists/lua-l/2011-10/msg00485.html | ||
279 | http://lua-users.org/wiki/LuaModuleFunctionCritiqued | ||
280 | |||
281 | On the other hand, Thing as such might just vanish and merge into | ||
282 | various Lua and metatable things. Seems that's what is going on. We | ||
283 | didn't really need much OO beyond this anyway. | ||
284 | 243 | ||
285 | Each "users session" (matrix-RAD term that came from Java | 244 | Each "users session" (matrix-RAD term that came from Java |
286 | applets/servlets) has a ThingSpace, which is a tree that holds | 245 | applets/servlets) has a ThingSpace, which is a tree that holds |
287 | everything else. It holds the class cache, commands, loaded modules, | 246 | everything else. It holds the class cache, commands, loaded modules, |
288 | variables and their values, widgets and their states. In matrix-RAD I | 247 | variables and their values, widgets and their states. In matrix-RAD I |
289 | built BonsiaTree and LeafLike, for the old FDO system I built dumbtrees. | 248 | built BonsiaTree and LeafLike, for the old FDO system I built dumbtrees. |
290 | Perhaps some combination of the two will work here? On the other hand, | ||
291 | with Lua tables, who needs trees? lol | ||
292 | |||
293 | Since skang Lua scripts should be defined as modules, we can use | ||
294 | module semantics instead of get/set - | ||
295 | |||
296 | local other = require('otherPackageName') | ||
297 | other.foo = 'stuff' | ||
298 | bar = other.foo | ||
299 | 249 | ||
300 | Other Thing things are - | 250 | Other Thing things are - |
301 | get/set The getter and setter. | 251 | get/set The getter and setter. |
@@ -311,91 +261,23 @@ Other Thing things are - | |||
311 | ]] | 261 | ]] |
312 | 262 | ||
313 | 263 | ||
314 | --[[ TODO | 264 | --[[ Stuff Java package |
315 | NOTE that skang.thing{} doesn't care what other names you pass in, they all get assigned to the thing. | ||
316 | 265 | ||
266 | In matrix-RAD Stuff took care of multi value Things, like database rows. | ||
317 | 267 | ||
318 | Widget - | 268 | Stuff is an abstract class that gets extended by other classes, like |
319 | Merging widgets might work to. B-) | 269 | SquealStuff, which was the only thing extending it. It dealt with the |
320 | This does make the entire "Things with the same name link automatically" deal work easily, since they ARE the same Thing. | 270 | basic "collection of things" stuff. Each individual thing was called a |
321 | 271 | stufflet. A final fooStuff would extend SquealStuff, and include an | |
322 | Widgets get a type as well, which would be label, button, edit, grid, etc. | 272 | array of strings called "stufflets" that at least named the stufflets, |
323 | A grid could even have sub types - grid,number,string,button,date. B-) | 273 | but could also include metadata and links to other Stuffs. |
324 | A required widget might mean that the window HAS to have one. | ||
325 | Default for a widget could be the default creation arguments - '"Press me", 1, 1, 10, 50'. | ||
326 | |||
327 | skang.thing('foo,s,fooAlias', 'Foo is a bar, not the drinking type.', function () print('foo') end, '', '"button", "The foo :"' 1, 1, 10, 50') | ||
328 | myButton = skang.widget('foo') -- Gets the default widget creation arguments. | ||
329 | myButton:colour(1, 2, 3, 4) | ||
330 | -- Use generic positional / named arguments for widget to, then we can do - | ||
331 | myEditor = skang.widget{'foo', "edit", "Edit foo :", 5, 15, 10, 100, look='edit.edj', colour={blue=20}, action='...'} | ||
332 | -- Using the Thing alias stuff, maybe we can do the "first stage tokenise" step after all - | ||
333 | myEditor = skang.widget{'foo', "edit", "Edit foo :", 5, 15, 10, 100, l='edit.edj', c={b=20}, a='...'} | ||
334 | myEditor:colour(1, 2, 3, 4, 5, 6, 7, 8) | ||
335 | myButton = 'Not default' -- myEditor and foo change to. Though now foo is a command, not a parameter, so maybe don't change that. | ||
336 | -- Though the 'quit' Thing could have a function that does quitting, this is just an example of NOT linking to a Thing. | ||
337 | -- If we had linked to this theoretical 'quit' Thing, then pushing that Quit button would invoke it's Thing function. | ||
338 | quitter = skang.widget(nil, 'button', 'Quit', 0.5, 0.5, 0.5, 0.5) | ||
339 | quitter:action('quit') | ||
340 | |||
341 | |||
342 | Squeal - | ||
343 | squeal.database('db', 'host', 'someDb', 'user', 'password') -> Should return a module. | ||
344 | local db = require 'someDbThing' -> Same as above, only the database details are encodode in the someDbThing source, OR come from someDbThing.properties. | ||
345 | db:getTable('stuff', 'someTable') -> Grabs the metadata, but not the rows. | ||
346 | db:read('stuff', 'select * from someTable'} -> Fills stuff up with several rows, including setting up the metadata for the columns. | ||
347 | stuff[1].field1 -> Is a Thing, with a stuff in the stuff metatable, that was created automatically from the database meta data. | ||
348 | stuff:read('someIndex') -> Grabs a single row that has the key 'someIndex', or perhaps multiple rows since this might have SQL under it. | ||
349 | stuff = db:read('stuff', 'select * from someTable where key='someIndex') | ||
350 | |||
351 | stuff:write() -> Write all rows to the database table. | ||
352 | stuff:write(1) -> Write one row to the database table. | ||
353 | stuff:stuff('field1').isValid = someFunction -- Should work, all stuff[key] shares the same stuff. | ||
354 | stuff:isValid(db) -> Validate the entire stuff against it's metadata at least. | ||
355 | window.stuff = stuff -> Window gets stuff as it's default stuff, any widgets with same names as the table fields get linked. | ||
356 | grid.stuff = stuff -> Replace contents of this grid widget with data from all the rows in stuff. | ||
357 | choice.stuff = stuff -> As in grid, but only using the keys. | ||
358 | widget.stuff = stuff:stuff('field1') -> This widget gets a particular stufflet. | ||
359 | widget would have to look up getmetatable(window.stuff).parent. Or maybe this should work some other way? | ||
360 | |||
361 | In all these cases above, stuff is a table that has a Thing metatable, so it has stuff. | ||
362 | It is also a Stuff. | ||
363 | Should include some way of specifyings details like key name, where string, etc. | ||
364 | getmetatable(stuff).__keyName | ||
365 | getmetatable(stuff).__squeal.where | ||
366 | And a way to link this database table to others, via the key of the other, as a field in this Stuff. | ||
367 | stuff:stuff('field0').__link = {parent, key, index} | ||
368 | In Java we had this - | ||
369 | |||
370 | public class PersonStuff extends SquealStuff | ||
371 | { | ||
372 | |||
373 | ... | ||
374 | |||
375 | public final static String FULLNAME = "fullname"; | ||
376 | |||
377 | public static final String keyField = "ID"; // Name of key field/s. | ||
378 | public static final String where = keyField + "='%k'"; | ||
379 | public static final String listName = "last"; | ||
380 | public static final String tables = "PEOPLE"; | ||
381 | public static final String select = null; | ||
382 | public static final String stufflets[] = | ||
383 | { | ||
384 | keyField, | ||
385 | "PASSWD_ID|net.matrix_rad.squeal.PasswdStuff|,OTHER", | ||
386 | "QUALIFICATION_IDS|net.matrix_rad.people.QualificationStuff|,OTHER", | ||
387 | "INTERESTING_IDS|net.matrix_rad.people.InterestingStuff|,OTHER", | ||
388 | "title", | ||
389 | "first", | ||
390 | "middle", | ||
391 | "last", | ||
392 | "suffix", | ||
393 | 274 | ||
394 | ... | 275 | There was various infrastructure for reading and writing Stuff, throwing |
276 | rows of Stuff into grids, having choices of Stuff, linking stufflets to | ||
277 | individual widgets, having default Stuffs for windows, validating | ||
278 | Stuffs, etc. | ||
395 | 279 | ||
396 | FULLNAME + "||,VARCHAR,512" | 280 | In Lua, setting up stuff has been folded into the general Thing stuff. |
397 | }; | ||
398 | } | ||
399 | 281 | ||
400 | ]] | 282 | ]] |
401 | 283 | ||
@@ -416,6 +298,11 @@ meta(table).__index and __newindex only work on table entries that don't exist. | |||
416 | Using both __index and __newindex, and keeping the actual values elsewhere, is called a proxy table. | 298 | Using both __index and __newindex, and keeping the actual values elsewhere, is called a proxy table. |
417 | meta(table).__call(table, ...) is called when trying to access table as a function - table(...). | 299 | meta(table).__call(table, ...) is called when trying to access table as a function - table(...). |
418 | 300 | ||
301 | It's worth repeating - | ||
302 | All variables in Lua are in some table somewhere, even if it's just the global environment table. | ||
303 | Metatables are only associated vith values, not variables. | ||
304 | Lua can only attach metatables to values that are tables, but C can attach metatables to any value. | ||
305 | |||
419 | 306 | ||
420 | A Thing is a managed variable stored in a parent proxy table, which is usually empty. | 307 | A Thing is a managed variable stored in a parent proxy table, which is usually empty. |
421 | So the values stored in this Thing are actually stored in meta(parent)__values[thing]. | 308 | So the values stored in this Thing are actually stored in meta(parent)__values[thing]. |
@@ -847,9 +734,11 @@ set = function (stuff, key, name, value) | |||
847 | end | 734 | end |
848 | end | 735 | end |
849 | 736 | ||
850 | thingasm('get', 'Get the current value of an existing Thing or metadata.', get, 'thing,key,name') | 737 | thingasm('get', 'Get the current value of an existing Thing or metadata.', get, 'thing,key,name') |
851 | thingasm('reset', 'Reset the current value of an existing Thing or metadata.', reset, 'thing,key,name') | 738 | thingasm('reset', 'Reset the current value of an existing Thing or metadata.', reset, 'thing,key,name') |
852 | thingasm('set', 'Set the current value of an existing Thing or metadata.', set, 'thing,key,name,data') | 739 | thingasm('set', 'Set the current value of an existing Thing or metadata.', set, 'thing,key,name,data') |
740 | |||
741 | |||
853 | thingasm('nada', 'Do nothing.', function () --[[ This function intentionally left blank. ]] end) | 742 | thingasm('nada', 'Do nothing.', function () --[[ This function intentionally left blank. ]] end) |
854 | 743 | ||
855 | 744 | ||
@@ -877,7 +766,6 @@ moduleEnd(_M) | |||
877 | 766 | ||
878 | end | 767 | end |
879 | 768 | ||
880 | -- NOTE - We have swapped acl and boss around from the Java version, since boss was usually blank. | ||
881 | -- Boss is the person that owns a Thing. | 769 | -- Boss is the person that owns a Thing. |
882 | 770 | ||
883 | --[[ The original Skang parameters and commands. | 771 | --[[ The original Skang parameters and commands. |
@@ -1037,6 +925,151 @@ access to the module. | |||
1037 | ]] | 925 | ]] |
1038 | 926 | ||
1039 | 927 | ||
928 | --[[ TODO | ||
929 | NOTE that skang.thing{} doesn't care what other names you pass in, they all get assigned to the thing. | ||
930 | |||
931 | |||
932 | Widget - | ||
933 | Should include functions for actually dealing with widgets, plus a way | ||
934 | of creating widgets via introspection. Should also allow access to | ||
935 | widget internals via table access. Lua code could look like this - | ||
936 | |||
937 | foo = widget.label(0, "0.1", 0.5, 0, 'Text goes here :") | ||
938 | -- Method style. | ||
939 | foo:colour(255, 255, 255, 0, 0, 100, 255, 0) | ||
940 | foo:hide() | ||
941 | foo:action("skang.load(some/skang/file.skang)") | ||
942 | -- Table style. | ||
943 | foo.action = "skang.load('some/skang/file.skang')" | ||
944 | foo.colour.r = 123 | ||
945 | foo.look('some/edje/file/somewhere.edj') | ||
946 | foo.help = 'This is a widget for labelling some foo.' | ||
947 | |||
948 | For widgets with "rows", which was handled by Stuff in skang, we could | ||
949 | maybe use the Lua concat operator via metatable. I think that works by | ||
950 | having the widget (a table) on one side of the concat or the other, and | ||
951 | the metatable function gets passed left and right sides, then must | ||
952 | return the result. Needs some experimentation, but this might look like | ||
953 | this - | ||
954 | |||
955 | this.bar = this.bar .. 'new choice' | ||
956 | this.bar = 'new first choice' .. this.bar | ||
957 | |||
958 | |||
959 | Widgets get a type as well, which would be label, button, edit, grid, etc. | ||
960 | A grid could even have sub types - grid,number,string,button,date. B-) | ||
961 | A required widget might mean that the window HAS to have one. | ||
962 | Default for a widget could be the default creation arguments - '"Press me", 1, 1, 10, 50'. | ||
963 | |||
964 | skang.thing('foo,s,fooAlias', 'Foo is a bar, not the drinking type.', function () print('foo') end, '', '"button", "The foo :"' 1, 1, 10, 50') | ||
965 | myButton = skang.widget('foo') -- Gets the default widget creation arguments. | ||
966 | myButton:colour(1, 2, 3, 4) | ||
967 | -- Use generic positional / named arguments for widget to, then we can do - | ||
968 | myEditor = skang.widget{'foo', "edit", "Edit foo :", 5, 15, 10, 100, look='edit.edj', colour={blue=20}, action='...'} | ||
969 | -- Using the Thing alias stuff, maybe we can do the "first stage tokenise" step after all - | ||
970 | myEditor = skang.widget{'foo', "edit", "Edit foo :", 5, 15, 10, 100, l='edit.edj', c={b=20}, a='...'} | ||
971 | myEditor:colour(1, 2, 3, 4, 5, 6, 7, 8) | ||
972 | myButton = 'Not default' -- myEditor and foo change to. Though now foo is a command, not a parameter, so maybe don't change that. | ||
973 | -- Though the 'quit' Thing could have a function that does quitting, this is just an example of NOT linking to a Thing. | ||
974 | -- If we had linked to this theoretical 'quit' Thing, then pushing that Quit button would invoke it's Thing function. | ||
975 | quitter = skang.widget(nil, 'button', 'Quit', 0.5, 0.5, 0.5, 0.5) | ||
976 | quitter:action('quit') | ||
977 | |||
978 | coordinates and sizes | ||
979 | |||
980 | Originally skang differentiated between pixels and character cells, | ||
981 | using plain integers to represent pixels, and _123 to represent | ||
982 | character cells. The skang TODO wanted to expand that to percentages | ||
983 | and relative numbers. We can't use _123 in Lua, so some other method | ||
984 | needs to be used. Should include those TODO items in this new design. | ||
985 | |||
986 | Specifying character cells should be done as strings - "123" | ||
987 | |||
988 | Percentages can be done as small floating point numbers between 0 and 1, | ||
989 | which is similar to Edje. Since Lua only has a floating point number | ||
990 | type, both 0 and 1 should still represent pixels / character cells - | ||
991 | |||
992 | 0.1, 0.5, "0.2", "0.9" | ||
993 | |||
994 | Relative numbers could be done as strings, with the widget to be | ||
995 | relative to, a + or -, then the number. This still leaves the problem | ||
996 | of telling if the number is pixels or character cells. Also, relative | ||
997 | to what part of the other widget? Some more thought needs to be put | ||
998 | into this. | ||
999 | |||
1000 | Another idea for relative numbers could be to have a coord object with | ||
1001 | various methods, so we could have something like - | ||
1002 | |||
1003 | widget:bottom(-10):right(5) -- 10 pixels below the bottom of widget, 5 pixels to the right of the right edge of widget. | ||
1004 | widget:width("12") -- 12 characters longer than the width of widget. | ||
1005 | |||
1006 | |||
1007 | Squeal - | ||
1008 | Squeal was the database driver interface for SquealStuff, the database | ||
1009 | version of Stuff. Maybe we could wrap esskyuehl? Not really in need of | ||
1010 | database stuff for now, but should keep it in mind. | ||
1011 | For SquealStuff, the metadata would be read from the SQL database automatically. | ||
1012 | |||
1013 | squeal.database('db', 'host', 'someDb', 'user', 'password') -> Should return a module. | ||
1014 | local db = require 'someDbThing' -> Same as above, only the database details are encodode in the someDbThing source, OR come from someDbThing.properties. | ||
1015 | db:getTable('stuff', 'someTable') -> Grabs the metadata, but not the rows. | ||
1016 | db:read('stuff', 'select * from someTable'} -> Fills stuff up with several rows, including setting up the metadata for the columns. | ||
1017 | stuff[1].field1 -> Is a Thing, with a stuff in the stuff metatable, that was created automatically from the database meta data. | ||
1018 | stuff:read('someIndex') -> Grabs a single row that has the key 'someIndex', or perhaps multiple rows since this might have SQL under it. | ||
1019 | stuff = db:read('stuff', 'select * from someTable where key='someIndex') | ||
1020 | |||
1021 | stuff:write() -> Write all rows to the database table. | ||
1022 | stuff:write(1) -> Write one row to the database table. | ||
1023 | stuff:stuff('field1').isValid = someFunction -- Should work, all stuff[key] shares the same stuff. | ||
1024 | stuff:isValid(db) -> Validate the entire stuff against it's metadata at least. | ||
1025 | window.stuff = stuff -> Window gets stuff as it's default stuff, any widgets with same names as the table fields get linked. | ||
1026 | grid.stuff = stuff -> Replace contents of this grid widget with data from all the rows in stuff. | ||
1027 | choice.stuff = stuff -> As in grid, but only using the keys. | ||
1028 | widget.stuff = stuff:stuff('field1') -> This widget gets a particular stufflet. | ||
1029 | widget would have to look up getmetatable(window.stuff).parent. Or maybe this should work some other way? | ||
1030 | |||
1031 | In all these cases above, stuff is a table that has a Thing metatable, so it has stuff. | ||
1032 | It is also a Stuff. | ||
1033 | Should include some way of specifyings details like key name, where string, etc. | ||
1034 | getmetatable(stuff).__keyName | ||
1035 | getmetatable(stuff).__squeal.where | ||
1036 | And a way to link this database table to others, via the key of the other, as a field in this Stuff. | ||
1037 | stuff:stuff('field0').__link = {parent, key, index} | ||
1038 | In Java we had this - | ||
1039 | |||
1040 | public class PersonStuff extends SquealStuff | ||
1041 | { | ||
1042 | |||
1043 | ... | ||
1044 | |||
1045 | public final static String FULLNAME = "fullname"; | ||
1046 | |||
1047 | public static final String keyField = "ID"; // Name of key field/s. | ||
1048 | public static final String where = keyField + "='%k'"; | ||
1049 | public static final String listName = "last"; | ||
1050 | public static final String tables = "PEOPLE"; | ||
1051 | public static final String select = null; | ||
1052 | public static final String stufflets[] = | ||
1053 | { | ||
1054 | keyField, | ||
1055 | "PASSWD_ID|net.matrix_rad.squeal.PasswdStuff|,OTHER", | ||
1056 | "QUALIFICATION_IDS|net.matrix_rad.people.QualificationStuff|,OTHER", | ||
1057 | "INTERESTING_IDS|net.matrix_rad.people.InterestingStuff|,OTHER", | ||
1058 | "title", | ||
1059 | "first", | ||
1060 | "middle", | ||
1061 | "last", | ||
1062 | "suffix", | ||
1063 | |||
1064 | ... | ||
1065 | |||
1066 | FULLNAME + "||,VARCHAR,512" | ||
1067 | }; | ||
1068 | } | ||
1069 | |||
1070 | ]] | ||
1071 | |||
1072 | |||
1040 | -- Gotta check out this _ENV thing, 5.2 only. Seems to replace the need for setfenv(). Seems like setfenv should do what we want, and is more backward compatible. | 1073 | -- Gotta check out this _ENV thing, 5.2 only. Seems to replace the need for setfenv(). Seems like setfenv should do what we want, and is more backward compatible. |
1041 | -- "_ENV is not supported directly in 5.1, so its use can prevent a module from remaining compatible with 5.1. | 1074 | -- "_ENV is not supported directly in 5.1, so its use can prevent a module from remaining compatible with 5.1. |
1042 | -- Maybe you can simulate _ENV with setfenv and trapping gets/sets to it via __index/__newindex metamethods, or just avoid _ENV." | 1075 | -- Maybe you can simulate _ENV with setfenv and trapping gets/sets to it via __index/__newindex metamethods, or just avoid _ENV." |