Advertisement
Guest User

ETK2 Nspire Lua GUI Library demo

a guest
Aug 8th, 2013
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 56.70 KB | None | 0 0
  1. ------------------------------------
  2. ---          DEMO script         ---
  3. ---      ETK By Jim Bauwens      ---
  4. --- Additions by Adrien Bertrand ---
  5. ------------------------------------
  6. ---  Real demo code : line 1234  ---
  7. ------------------------------------
  8.  
  9.  
  10. ------------------------------------------------------------------
  11. -- Overall Global Variables                    --
  12. ------------------------------------------------------------------
  13.  
  14. kXSize = 1 -- will get changed
  15. kYSize = 1 -- will get changed
  16.  
  17. function math.round(num, idp)
  18.   return tonumber(string.format("%." .. (idp or 0) .. "f", num))
  19. end
  20.  
  21. --
  22. -- Uses BetterLuaAPI : https://github.com/adriweb/BetterLuaAPI-for-TI-Nspire
  23. --
  24.  
  25. a_acute = string.uchar(225)
  26. a_circ = string.uchar(226)
  27. a_tilde = string.uchar(227)
  28. a_diaer = string.uchar(228)
  29. a_ring = string.uchar(229)
  30. e_acute = string.uchar(233)
  31. e_grave = string.uchar(232)
  32. o_acute = string.uchar(243)
  33. o_circ = string.uchar(244)
  34. l_alpha = string.uchar(945)
  35. l_beta = string.uchar(946)
  36. l_omega = string.uchar(2126)
  37. sup_plus = string.uchar(8314)
  38. sup_minus = string.uchar(8315)
  39. right_arrow = string.uchar(8594)
  40.  
  41. Color = {
  42.     ["black"] = { 0, 0, 0 },
  43.     ["red"] = { 255, 0, 0 },
  44.     ["green"] = { 0, 255, 0 },
  45.     ["blue"] = { 0, 0, 255 },
  46.     ["white"] = { 255, 255, 255 },
  47.     ["brown"] = { 165, 42, 42 },
  48.     ["cyan"] = { 0, 255, 255 },
  49.     ["darkblue"] = { 0, 0, 139 },
  50.     ["darkred"] = { 139, 0, 0 },
  51.     ["gold"] = { 255, 215, 0 },
  52.     ["gray"] = { 127, 127, 127 },
  53.     ["grey"] = { 127, 127, 127 },
  54.     ["lightblue"] = { 173, 216, 230 },
  55.     ["lightgreen"] = { 144, 238, 144 },
  56.     ["magenta"] = { 255, 0, 255 },
  57.     ["maroon"] = { 128, 0, 0 },
  58.     ["navyblue"] = { 159, 175, 223 },
  59.     ["orange"] = { 255, 165, 0 },
  60.     ["pink"] = { 255, 192, 203 },
  61.     ["purple"] = { 128, 0, 128 },
  62.     ["royalblue"] = { 65, 105, 225 },
  63.     ["silver"] = { 192, 192, 192 },
  64.     ["violet"] = { 238, 130, 238 },
  65.     ["yellow"] = { 255, 255, 0 }
  66. }
  67. Color.mt = { __index = function() return { 0, 0, 0 } end }
  68. setmetatable(Color, Color.mt)
  69.  
  70. function copyTable(t)
  71.     local t2 = {}
  72.     for k, v in pairs(t) do
  73.         t2[k] = v
  74.     end
  75.     return t2
  76. end
  77.  
  78. function deepcopy(t) -- This function recursively copies a table's contents, and ensures that metatables are preserved. That is, it will correctly clone a pure Lua object.
  79.     if type(t) ~= 'table' then return t end
  80.     local mt = getmetatable(t)
  81.     local res = {}
  82.     for k, v in pairs(t) do
  83.         if type(v) == 'table' then
  84.             v = deepcopy(v)
  85.         end
  86.         res[k] = v
  87.     end
  88.     setmetatable(res, mt)
  89.     return res
  90. end
  91.  
  92. -- from http://snippets.luacode.org/snippets/Deep_copy_of_a_Lua_Table_2
  93.  
  94. function utf8(nbr)
  95.     return string.uchar(nbr)
  96. end
  97.  
  98. function test(arg)
  99.     return arg and 1 or 0
  100. end
  101.  
  102. function screenRefresh()
  103.     return platform.window:invalidate()
  104. end
  105.  
  106. function pww()
  107.     return platform.window:width()
  108. end
  109.  
  110. function pwh()
  111.     return platform.window:height()
  112. end
  113.  
  114. function drawPoint(gc, x, y)
  115.     gc:fillRect(x, y, 1, 1)
  116. end
  117.  
  118. function drawCircle(gc, x, y, diam)
  119.     gc:drawArc(x, y, diam, diam, 0, 360)
  120. end
  121.  
  122. function fillCircle(gc, x, y, diam)
  123.     gc:fillArc(x, y, diam, diam, 0, 360)
  124. end
  125.  
  126.  
  127. function drawCenteredString(gc, str)
  128.     gc:drawString(str, .5 * (pww() - gc:getStringWidth(str)), .5 * pwh(), "middle")
  129. end
  130.  
  131. function drawXCenteredString(gc, str, y)
  132.     gc:drawString(str, .5 * (pww() - gc:getStringWidth(str)), y, "top")
  133. end
  134.  
  135. function setColor(gc, theColor)
  136.     if type(theColor) == "string" then
  137.         theColor = string.lower(theColor)
  138.         if type(Color[theColor]) == "table" then gc:setColorRGB(unpack(Color[theColor])) end
  139.     elseif type(theColor) == "table" then
  140.         gc:setColorRGB(unpack(theColor))
  141.     end
  142. end
  143.  
  144. function verticalBar(gc, x)
  145.     gc:fillRect(x, 0, 1, pwh())
  146. end
  147.  
  148. function horizontalBar(gc, y)
  149.     gc:fillRect(0, y, pww(), 1)
  150. end
  151.  
  152. function nativeBar(gc, screen, y)
  153.     gc:setColorRGB(128,128,128)
  154.     gc:fillRect(screen.x+5, screen.y+y, screen.w-10, 2)
  155. end
  156.  
  157. function drawSquare(gc, x, y, l)
  158.     gc:drawPolyLine({ (x - l / 2), (y - l / 2), (x + l / 2), (y - l / 2), (x + l / 2), (y + l / 2), (x - l / 2), (y + l / 2), (x - l / 2), (y - l / 2) })
  159. end
  160.  
  161. function drawRoundRect(gc, x, y, wd, ht, rd) -- wd = width, ht = height, rd = radius of the rounded corner
  162.     x = x - wd / 2 -- let the center of the square be the origin (x coord)
  163.     y = y - ht / 2 -- same for y coord
  164.     if rd > ht / 2 then rd = ht / 2 end -- avoid drawing cool but unexpected shapes. This will draw a circle (max rd)
  165.     gc:drawLine(x + rd, y, x + wd - (rd), y);
  166.     gc:drawArc(x + wd - (rd * 2), y + ht - (rd * 2), rd * 2, rd * 2, 270, 90);
  167.     gc:drawLine(x + wd, y + rd, x + wd, y + ht - (rd));
  168.     gc:drawArc(x + wd - (rd * 2), y, rd * 2, rd * 2, 0, 90);
  169.     gc:drawLine(x + wd - (rd), y + ht, x + rd, y + ht);
  170.     gc:drawArc(x, y, rd * 2, rd * 2, 90, 90);
  171.     gc:drawLine(x, y + ht - (rd), x, y + rd);
  172.     gc:drawArc(x, y + ht - (rd * 2), rd * 2, rd * 2, 180, 90);
  173. end
  174.  
  175. function fillRoundRect(gc, x, y, wd, ht, radius) -- wd = width and ht = height -- renders badly when transparency (alpha) is not at maximum >< will re-code later
  176.     if radius > ht / 2 then radius = ht / 2 end -- avoid drawing cool but unexpected shapes. This will draw a circle (max radius)
  177.     gc:fillPolygon({ (x - wd / 2), (y - ht / 2 + radius), (x + wd / 2), (y - ht / 2 + radius), (x + wd / 2), (y + ht / 2 - radius), (x - wd / 2), (y + ht / 2 - radius), (x - wd / 2), (y - ht / 2 + radius) })
  178.     gc:fillPolygon({ (x - wd / 2 - radius + 1), (y - ht / 2), (x + wd / 2 - radius + 1), (y - ht / 2), (x + wd / 2 - radius + 1), (y + ht / 2), (x - wd / 2 + radius), (y + ht / 2), (x - wd / 2 + radius), (y - ht / 2) })
  179.     x = x - wd / 2 -- let the center of the square be the origin (x coord)
  180.     y = y - ht / 2 -- same
  181.     gc:fillArc(x + wd - (radius * 2), y + ht - (radius * 2), radius * 2, radius * 2, 1, -91);
  182.     gc:fillArc(x + wd - (radius * 2), y, radius * 2, radius * 2, -2, 91);
  183.     gc:fillArc(x, y, radius * 2, radius * 2, 85, 95);
  184.     gc:fillArc(x, y + ht - (radius * 2), radius * 2, radius * 2, 180, 95);
  185. end
  186.  
  187. function drawLinearGradient(gc, color1, color2)
  188.     -- syntax would be : color1 and color2 as {r,g,b}.
  189.     -- don't really know how to do that. probably converting to hue/saturation/light mode and change the hue.
  190.     -- todo with unpack(color1) and unpack(color2)
  191. end
  192.  
  193. function bigText(gc)
  194.     gc:setFont("serif", "b", 18)
  195. end
  196.  
  197. function normalText(gc)
  198.     gc:setFont("sansserif", "r", 12)
  199. end
  200.  
  201.  
  202.  
  203. local tstart = timer.start
  204. function timer.start(ms)
  205.     if not timer.isRunning then
  206.         tstart(ms)
  207.     end
  208.     timer.isRunning = true
  209. end
  210. local tstop = timer.stop
  211. function timer.stop()
  212.     timer.isRunning = false
  213.     tstop()
  214. end
  215.  
  216.  
  217.  
  218. stdout  = print
  219.  
  220. function pprint(...)
  221.     stdout(...)
  222.     local out   = ""
  223.     for _,v in ipairs({...}) do
  224.         out =   out .. (_==1 and "" or "    ") .. tostring(v)
  225.     end
  226.     var.store("print", out)
  227. end
  228.  
  229.  
  230. function Pr(n, d, s, ex)
  231.     local nc    = tonumber(n)
  232.     if nc and nc<math.abs(nc) then
  233.         return s-ex-(type(n)== "number" and math.abs(n) or (.01*s*math.abs(nc)))
  234.     else
  235.         return (type(n)=="number" and n or (type(n)=="string" and .01*s*nc or d))
  236.     end
  237. end
  238.  
  239. -- Apply an extension on a class, and return our new frankenstein
  240. function addExtension(oldclass, extension)
  241.     local newclass  = class(oldclass)
  242.     for key, data in pairs(extension) do
  243.         newclass[key]   = data
  244.     end
  245.     return newclass
  246. end
  247.  
  248. clipRectData    = {}
  249.  
  250. function gc_clipRect(gc, what, x, y, w, h)
  251.     if what == "set" and clipRectData.current then
  252.         clipRectData.old    = clipRectData.current
  253.        
  254.     elseif what == "subset" and clipRectData.current then
  255.         clipRectData.old    = clipRectData.current
  256.         x   = clipRectData.old.x<x and x or clipRectData.old.x
  257.         y   = clipRectData.old.y<y and y or clipRectData.old.y
  258.         h   = clipRectData.old.y+clipRectData.old.h > y+h and h or clipRectData.old.y+clipRectData.old.h-y
  259.         w   = clipRectData.old.x+clipRectData.old.w > x+w and w or clipRectData.old.x+clipRectData.old.w-x
  260.         what = "set"
  261.     elseif what == "subset" then
  262.         what = "set"   
  263.     elseif what == "restore" and clipRectData.old then
  264.         --gc:clipRect("reset")
  265.         what = "set"
  266.         x   = clipRectData.old.x
  267.         y   = clipRectData.old.y
  268.         h   = clipRectData.old.h
  269.         w   = clipRectData.old.w
  270.     elseif what == "restore" then
  271.         what = "reset"
  272.     end
  273.    
  274.     gc:clipRect(what, x, y, w, h)
  275.     if x and y and w and h then clipRectData.current = {x=x,y=y,w=w,h=h} end
  276. end
  277.  
  278. ------------------------------------------------------------------
  279. --                        Screen  Class                         --
  280. ------------------------------------------------------------------
  281.  
  282. Screen  =   class()
  283.  
  284. Screens =   {}
  285.  
  286. function push_screen(screen, ...)
  287.     current_screen():screenLoseFocus()
  288.     table.insert(Screens, screen)
  289.     platform.window:invalidate()
  290.     current_screen():pushed(...)
  291. end
  292.  
  293. function only_screen(screen, ...)
  294.     current_screen():screenLoseFocus()
  295.     Screens =   {screen}
  296.     platform.window:invalidate()
  297.     screen:pushed(...) 
  298. end
  299.  
  300. function remove_screen(...)
  301.     platform.window:invalidate()
  302.     current_screen():removed(...)
  303.     res=table.remove(Screens)
  304.     current_screen():screenGetFocus()
  305.     return res
  306. end
  307.  
  308. function current_screen()
  309.     return Screens[#Screens] or DummyScreen
  310. end
  311.  
  312. function Screen:init(xx,yy,ww,hh)
  313.     self.yy =   yy
  314.     self.xx =   xx
  315.     self.hh =   hh
  316.     self.ww =   ww
  317.    
  318.    
  319.     self:ext()
  320.     self:size(0)
  321. end
  322.  
  323. function Screen:ext()
  324. end
  325.  
  326. function Screen:size()
  327.     local screenH   =   platform.window:height()
  328.     local screenW   =   platform.window:width()
  329.  
  330.     if screenH  == 0 then screenH=212 end
  331.     if screenW  == 0 then screenW=318 end
  332.  
  333.     self.=   math.floor(Pr(self.xx, 0, screenW, 0)+.5)
  334.     self.=   math.floor(Pr(self.yy, 0, screenH, 0)+.5)
  335.     self.=   math.floor(Pr(self.ww, screenW, screenW, 0)+.5)
  336.     self.=   math.floor(Pr(self.hh, screenH, screenH, 0)+.5)
  337. end
  338.  
  339.  
  340. function Screen:pushed() end
  341. function Screen:removed() end
  342. function Screen:screenLoseFocus() end
  343. function Screen:screenGetFocus() end
  344.  
  345. function Screen:draw(gc)
  346.     self:size()
  347.     self:paint(gc)
  348. end
  349.  
  350. function Screen:paint(gc) end
  351.  
  352. function Screen:invalidate()
  353.     platform.window:invalidate(self.x ,self.y , self.w, self.h)
  354. end
  355.  
  356. function Screen:arrowKey(arrw)  end
  357. function Screen:enterKey()  end
  358. function Screen:backspaceKey()  end
  359. function Screen:escapeKey() end
  360. function Screen:tabKey()    end
  361. function Screen:backtabKey()    end
  362. function Screen:clearKey()  end
  363. function Screen:charIn(ch)  end
  364. function Screen:timer() end
  365. function Screen:mouseDown(x,y)  end
  366. function Screen:mouseUp(x,y)    end
  367. function Screen:mouseMove(x,y)  end
  368. function Screen:contextMenu()   end
  369. function Screen:resize(x,y) end
  370. function Screen:grabDown(x,y) end
  371.  
  372. function Screen:appended() end
  373.  
  374. function Screen:destroy()
  375.     self    = nil
  376. end
  377.  
  378. ------------------------------------------------------------------
  379. --                   WidgetManager Extension                    --
  380. ------------------------------------------------------------------
  381.  
  382. WidgetManager   = {}
  383.  
  384. function WidgetManager:ext()
  385.     self.widgets    =   {}
  386.     self.focus  =   0
  387. end
  388.  
  389. function WidgetManager:appendWidget(widget, xx, yy)
  390.     widget.xx   =   xx
  391.     widget.yy   =   yy
  392.     widget.parent   =   self
  393.     widget:size()
  394.    
  395.     widget.pid  =   #self.widgets
  396.     table.insert(self.widgets, widget)
  397.    
  398.     widget:appended(self)
  399.     return self
  400. end
  401.  
  402. function WidgetManager:removeWidget(widget)
  403.     --table.remove(self.widgets, widget.pid)
  404.     --TODO !
  405. end
  406.  
  407. function WidgetManager:cleanWidgets()
  408.     self.widgets = {}
  409.     self.focus = 0
  410. end
  411.  
  412. function WidgetManager:getWidget()
  413.     return self.widgets[self.focus]
  414. end
  415.  
  416. function WidgetManager:drawWidgets(gc)
  417.     for _, widget in pairs(self.widgets) do
  418.         widget:size()
  419.         widget:draw(gc)
  420.        
  421.         gc:setColorRGB(0,0,0)
  422.     end
  423. end
  424.  
  425. function WidgetManager:postPaint(gc)
  426. end
  427.  
  428. function WidgetManager:draw(gc)
  429.     self:size()
  430.     self:paint(gc)
  431.     self:drawWidgets(gc)
  432.     self:postPaint(gc)
  433. end
  434.  
  435. function WidgetManager:loop(n) end
  436.  
  437. function WidgetManager:stealFocus(n)
  438.     local oldfocus=self.focus
  439.     if oldfocus~=0 then
  440.         local veto  = self:getWidget():loseFocus(n)
  441.         if veto == -1 then
  442.             return -1, oldfocus
  443.         end
  444.         self:getWidget().hasFocus   =   false
  445.         self.focus  = 0
  446.     end
  447.     return 0, oldfocus
  448. end
  449.  
  450. function WidgetManager:focusChange() end
  451.  
  452. function WidgetManager:switchFocus(n, b)
  453.     if n~=0 and #self.widgets>0 then
  454.         local veto, focus   = self:stealFocus(n)
  455.         if veto == -1 then
  456.             return -1
  457.         end
  458.        
  459.         local looped
  460.         self.focus  =   focus + n
  461.         if self.focus>#self.widgets then
  462.             self.focus  =   1
  463.             looped  = true
  464.         elseif self.focus<1 then
  465.             self.focus  =   #self.widgets
  466.             looped  = true
  467.         end
  468.         if looped and self.noloop and not b then
  469.             self.focus  = focus
  470.             self:loop(n)
  471.         else
  472.             self:getWidget().hasFocus   =   true   
  473.             self:getWidget():getFocus(n)
  474.         end
  475.     end
  476.     self:focusChange()
  477. end
  478.  
  479.  
  480. function WidgetManager:arrowKey(arrow) 
  481.     if self.focus~=0 then
  482.         self:getWidget():arrowKey(arrow)
  483.     end
  484.     self:invalidate()
  485. end
  486.  
  487. function WidgetManager:enterKey()  
  488.     if self.focus~=0 then
  489.         self:getWidget():enterKey()
  490.     end
  491.     self:invalidate()
  492. end
  493.  
  494. function WidgetManager:backspaceKey()
  495.     if self.focus~=0 then
  496.         self:getWidget():backspaceKey()
  497.     end
  498.     self:invalidate()
  499. end
  500.  
  501. function WidgetManager:escapeKey() 
  502.     if self.focus~=0 then
  503.         self:getWidget():escapeKey()
  504.     end
  505.     self:invalidate()
  506. end
  507.  
  508. function WidgetManager:clearKey()  
  509.     if self.focus~=0 then
  510.         self:getWidget():clearKey()
  511.     end
  512.     self:invalidate()
  513. end
  514.  
  515. function WidgetManager:tabKey()
  516.     self:switchFocus(1)
  517.     self:invalidate()
  518. end
  519.  
  520. function WidgetManager:backtabKey()
  521.     self:switchFocus(-1)
  522.     self:invalidate()
  523. end
  524.  
  525. function WidgetManager:charIn(char)
  526.     if self.focus~=0 then
  527.         self:getWidget():charIn(char)
  528.     end
  529.     self:invalidate()
  530. end
  531.  
  532. function WidgetManager:getWidgetIn(x, y)
  533.     for n, widget in pairs(self.widgets) do
  534.         local wox   = widget.ox or 0
  535.         local woy   = widget.oy or 0
  536.         if x>=widget.x-wox and y>=widget.y-wox and x<widget.x+widget.w-wox and y<widget.y+widget.h-woy then
  537.             return n, widget
  538.         end
  539.     end
  540. end
  541.  
  542. function WidgetManager:mouseDown(x, y)
  543.     local n, widget =   self:getWidgetIn(x, y)
  544.     if n then
  545.         if self.focus~=0 and self.focus~=n then self:getWidget().hasFocus = false self:getWidget():loseFocus()  end
  546.         self.focus  =   n
  547.        
  548.         widget.hasFocus =   true
  549.         widget:getFocus()
  550.  
  551.         widget:mouseDown(x, y)
  552.         self:focusChange()
  553.     else
  554.         if self.focus~=0 then self:getWidget().hasFocus = false self:getWidget():loseFocus() end
  555.         self.focus  =   0
  556.     end
  557. end
  558.  
  559. function WidgetManager:mouseUp(x, y)
  560.     if self.focus~=0 then
  561.         self:getWidget():mouseUp(x, y)
  562.     end
  563.     self:invalidate()
  564. end
  565.  
  566. function WidgetManager:mouseMove(x, y)
  567.     if self.focus~=0 then
  568.         self:getWidget():mouseMove(x, y)
  569.     end
  570. end
  571.  
  572. --------------------------
  573. -- Our new frankenstein --
  574. --------------------------
  575.  
  576. WScreen = addExtension(Screen, WidgetManager)
  577.  
  578.  
  579.  
  580. --Dialog screen
  581.  
  582. Dialog  =   class(WScreen)
  583.  
  584. function Dialog:init(title,xx,yy,ww,hh)
  585.     self.yy =   yy
  586.     self.xx =   xx
  587.     self.hh =   hh
  588.     self.ww =   ww
  589.     self.title  =   title
  590.     self:size()
  591.    
  592.     self.widgets    =   {}
  593.     self.focus  =   0
  594. end
  595.  
  596. function Dialog:paint(gc)
  597.     self.xx = (pww()-self.w)/2
  598.     self.yy = (pwh()-self.h)/2
  599.     self.x, self.= self.xx, self.yy
  600.    
  601.     gc:setFont("sansserif","r",10)
  602.     gc:setColorRGB(224,224,224)
  603.     gc:fillRect(self.x, self.y, self.w, self.h)
  604.  
  605.     for i=1, 14,2 do
  606.         gc:setColorRGB(32+i*3, 32+i*4, 32+i*3)
  607.         gc:fillRect(self.x, self.y+i, self.w,2)
  608.     end
  609.     gc:setColorRGB(32+16*3, 32+16*4, 32+16*3)
  610.     gc:fillRect(self.x, self.y+15, self.w, 10)
  611.    
  612.     gc:setColorRGB(128,128,128)
  613.     gc:drawRect(self.x, self.y, self.w, self.h)
  614.     gc:drawRect(self.x-1, self.y-1, self.w+2, self.h+2)
  615.    
  616.     gc:setColorRGB(96,100,96)
  617.     gc:fillRect(self.x+self.w+1, self.y, 1, self.h+2)
  618.     gc:fillRect(self.x, self.y+self.h+2, self.w+3, 1)
  619.    
  620.     gc:setColorRGB(104,108,104)
  621.     gc:fillRect(self.x+self.w+2, self.y+1, 1, self.h+2)
  622.     gc:fillRect(self.x+1, self.y+self.h+3, self.w+3, 1)
  623.     gc:fillRect(self.x+self.w+3, self.y+2, 1, self.h+2)
  624.     gc:fillRect(self.x+2, self.y+self.h+4, self.w+2, 1)
  625.            
  626.     gc:setColorRGB(255,255,255)
  627.     gc:drawString(self.title, self.x + 4, self.y+2, "top")
  628.    
  629.     self:postPaint(gc)
  630. end
  631.  
  632. function Dialog:postPaint() end
  633.  
  634.  
  635.  
  636.  
  637.  
  638. ---
  639. -- The dummy screen
  640. ---
  641.  
  642. DummyScreen = Screen()
  643.  
  644.  
  645.  
  646. function uCol(col)
  647.     return col[1] or 0, col[2] or 0, col[3] or 0
  648. end
  649.  
  650. function textLim(gc, text, max)
  651.     local ttext, out = "",""
  652.     local width = gc:getStringWidth(text)
  653.     if width<max then
  654.         return text, width
  655.     else
  656.         for i=1, #text do
  657.             ttext   = text:usub(1, i)
  658.             if gc:getStringWidth(ttext .. "..")>max then
  659.                 break
  660.             end
  661.             out = ttext
  662.         end
  663.         return out .. "..", gc:getStringWidth(out .. "..")
  664.     end
  665. end
  666.  
  667.  
  668. ------------------------------------------------------------------
  669. --                        Widget  Class                         --
  670. ------------------------------------------------------------------
  671.  
  672. Widget  =   class(Screen)
  673.  
  674. function Widget:init()
  675.     self.dw =   10
  676.     self.dh =   10
  677.    
  678.     self:ext()
  679. end
  680.  
  681. function Widget:setSize(w, h)
  682.     self.ww = w or self.ww
  683.     self.hh = h or self.hh
  684. end
  685.  
  686. function Widget:setPos(x, y)
  687.     self.xx = x or self.xx
  688.     self.yy = y or self.yy
  689. end
  690.  
  691. function Widget:size(n)
  692.     if n then return end
  693.     self.=   math.floor(Pr(self.ww, self.dw, self.parent.w, 0)+.5)
  694.     self.=   math.floor(Pr(self.hh, self.dh, self.parent.h, 0)+.5)
  695.     self.rx =   math.floor(Pr(self.xx, 0, self.parent.w, self.w)+.5)
  696.     self.ry =   math.floor(Pr(self.yy, 0, self.parent.h, self.h)+.5)
  697.     self.=   self.parent.x + self.rx
  698.     self.=   self.parent.y + self.ry
  699. end
  700.  
  701. function Widget:giveFocus()
  702.     if self.parent.focus~=0 then
  703.         local veto  = self.parent:stealFocus()
  704.         if veto == -1 then
  705.             return -1
  706.         end    
  707.     end
  708.    
  709.     self.hasFocus   =   true
  710.     self.parent.focus   =   self.pid
  711.     self:getFocus()
  712. end
  713.  
  714. function Widget:getFocus() end
  715. function Widget:loseFocus() end
  716. function Widget:enterKey()
  717.     self.parent:switchFocus(1)
  718. end
  719. function Widget:arrowKey(arrow)
  720.     if arrow=="up" then
  721.         self.parent:switchFocus(self.focusUp or -1)
  722.     elseif arrow=="down"  then
  723.         self.parent:switchFocus(self.focusDown or 1)
  724.     elseif arrow=="left" then
  725.         self.parent:switchFocus(self.focusLeft or -1)
  726.     elseif arrow=="right"  then
  727.         self.parent:switchFocus(self.focusRight or 1)  
  728.     end
  729. end
  730.  
  731.  
  732. WWidget = addExtension(Widget, WidgetManager)
  733.  
  734.  
  735. ------------------------------------------------------------------
  736. --                        Sample Widget                         --
  737. ------------------------------------------------------------------
  738.  
  739. -- First, create a new class based on Widget
  740. box =   class(Widget)
  741.  
  742. -- Init. You should define self.dh and self.dw, in case the user doesn't supply correct width/height values.
  743. -- self.ww and self.hh can be a number or a string. If it's a number, the width will be that amount of pixels.
  744. -- If it's a string, it will be interpreted as % of the parent screen size.
  745. -- These values will be used to calculate self.w and self.h (don't write to this, it will overwritten everytime the widget get's painted)
  746. -- self.xx and self.yy will be set when appending the widget to a screen. This value support the same % method (in a string)
  747. -- They will be used to calculate self.x and self.h
  748. function box:init(ww,hh,t)
  749.     self.dh = 10
  750.     self.dw = 10
  751.     self.ww = ww
  752.     self.hh = hh
  753.     self.= t
  754. end
  755.  
  756. -- Paint. Here you can paint your widget stuff
  757. -- Variable you can use:
  758. -- self.x, self.y   : numbers, x and y coordinates of the widget relative to screen. So it's the actual pixel position on the screen.
  759. -- self.w, self.h   : numbers, w and h of widget
  760. -- many others
  761.  
  762. function box:paint(gc)
  763.     gc:setColorRGB(0,0,0)
  764.    
  765.     -- Do I have focus?
  766.     if self.hasFocus then
  767.         -- Yes, draw a filled black square
  768.         gc:fillRect(self.x, self.y, self.w, self.h)
  769.     else
  770.         -- No, draw only the outline
  771.         gc:drawRect(self.x, self.y, self.w, self.h)
  772.     end
  773.    
  774.     gc:setColorRGB(128,128,128)
  775.     if self.t then
  776.         gc:drawString(self.t,self.x+2,self.y+2,"top")
  777.     end
  778. end
  779.  
  780.  
  781. ------------------------------------------------------------------
  782. -- Input Widget                         --
  783. ------------------------------------------------------------------
  784.  
  785.  
  786. sInput = class(Widget)
  787.  
  788. function sInput:init(callback)
  789.     self.dw = 25
  790.     self.dh = 20
  791.  
  792.     self.value = ""
  793.     self.bgcolor = { 255, 255, 255 }
  794.     self.disabledcolor = { 128, 128, 128 }
  795.     self.textcolor = { 0, 0, 0 }
  796.     self.font = { "sansserif", "r", 10 }
  797.     self.disabled = false
  798.     --self.capsOnly = true -- this activity only...
  799.     --self.number = true -- this activity
  800.     self.centeredText = true
  801.     self.callback = callback
  802. end
  803.  
  804. function sInput:paint(gc)
  805.     self.gc = gc
  806.     local x = self.x
  807.     local y = self.y
  808.  
  809.     gc:setFont(uCol(self.font))
  810.     gc:setColorRGB(uCol(self.bgcolor))
  811.     gc:fillRect(x + 2, y + 2, self.w - 3, self.h - 3)
  812.  
  813.     gc:setColorRGB(0, 0, 0)
  814.     if not self.hasFocus and not self.disabled then
  815.         gc:setPen("thin", "dashed")
  816.         gc:drawRect(x, y, self.w, self.h)
  817.         gc:setPen("thin", "smooth")
  818.     end
  819.     if self.showBorder then
  820.         gc:drawRect(x, y, self.w, self.h)
  821.     end
  822.  
  823.     if self.hasFocus and not self.disabled then
  824.         gc:drawRect(x, y, self.w, self.h)
  825.     end
  826.    
  827.     if self.hasFocus and not self.disabled then
  828.         gc:drawRect(x-1, y-1, self.w+2, self.h+2)
  829.     end
  830.  
  831.     local text = self.value
  832.     local p = 0
  833.  
  834.  
  835.     --gc_clipRect(gc, "subset", x, y, self.w, self.h)
  836.  
  837.     --[[
  838.      while true do
  839.          if p==#self.value then break end
  840.          p  =   p + 1
  841.          text   =   self.value:sub(-p, -p) .. text
  842.          if gc:getStringWidth(text) > (self.w - 8) then
  843.              text   =   text:sub(2,-1)
  844.              break
  845.          end
  846.      end
  847.      --]]
  848.  
  849.     if --[[self.disabled or]] self.value == "" then
  850.         gc:setColorRGB(uCol(self.disabledcolor))
  851.     end
  852.     if self.value == "" then
  853.         text = self.placeholder or ""
  854.         gc:setFont("serif", "i", 12)
  855.         --self.usingPlaceholder = true
  856.     end
  857.     gc:setColorRGB(unpack(self.textcolor))
  858.     local strwidth = gc:getStringWidth(text)
  859.  
  860.     if strwidth < self.w - 4 or not self.hasFocus then
  861.         gc:drawString(text, self.centeredText and 0.5 * ((2 * self.x + self.w) - gc:getStringWidth(text)) or self.x + 4, y - 1, "top")
  862.     else
  863.         gc:drawString(text, x - 4 + self.w - strwidth, y - 1, "top")
  864.     end
  865.  
  866.     if self.hasFocus and self.value ~= "" and not self.disabled then -- draw cursor
  867.         --  gc:fillRect(self.x+(text==self.value and strwidth+2 or self.w-4)+(self.centeredText and 0.15*((2*self.x+self.w)-3*gc:getStringWidth(self.value)) or 0), self.y, 1, self.h)
  868.     end
  869.  
  870.     gc_clipRect(gc, "restore")
  871. end
  872.  
  873. function sInput:charIn(char)
  874.     if self.disabled or (self.number and not tonumber(self.value .. char)) then --or char~="," then
  875.         return
  876.     end
  877.     --char = (char == ",") and "." or char
  878.     self.value = self.value .. (self.capsOnly and char:upper() or char)
  879. end
  880.  
  881. function sInput:backspaceKey()
  882.     if not self.disabled then
  883.         self.value = self.value:usub(1, -2)
  884.     end
  885. end
  886.  
  887. function sInput:enterKey()
  888.     if self.callback then self.callback() end
  889. end
  890.  
  891. function sInput:enable()
  892.     self.disabled = false
  893. end
  894.  
  895. function sInput:disable()
  896.     self.disabled = true
  897. end
  898.  
  899.  
  900.  
  901.  
  902.  
  903.  
  904.  
  905. ------------------------------------------------------------------
  906. -- Label Widget                         --
  907. ------------------------------------------------------------------
  908.  
  909. sLabel = class(Widget)
  910.  
  911. function sLabel:init(text, options, widget)
  912.     self.widget = widget
  913.     self.text = text
  914.     self.ww = 30
  915.    
  916.     self.options = options or {}
  917.    
  918.     self.font = self.options.font or "sansserif"
  919.     self.style = self.options.style or "r"
  920.     self.textSize = self.options.size or 10
  921.     self.decoration = self.options.decoration
  922.  
  923.     self.hh = 20
  924.     self.lim = false
  925.     self.color = { 0, 0, 0 }
  926.     self.color = self.options.color or self.color
  927.     self.font = { self.font, self.style, self.textSize }
  928.     self.p = "top"
  929. end
  930.  
  931. function sLabel:paint(gc)
  932.     gc:setFont(uCol(self.font))
  933.    
  934.     --gc:setColorRGB(255, 255, 255)
  935.     --gc:fillRect(self.x, self.y, 3*self.w, self.h)    
  936.    
  937.     gc:setColorRGB(uCol(self.color))
  938.  
  939.     local text = ""
  940.     local ttext
  941.     if self.lim then
  942.         text, self.dw = textLim(gc, self.text, self.w)
  943.     else
  944.         text = self.text
  945.     end
  946.     self.textW, self.textH = gc:getStringWidth(text), gc:getStringHeight(text)
  947.    
  948.     for i, line in ipairs(tostring(text):split("\n")) do
  949.         gc:drawString(line, self.x, self.y + (i-1)*self.textH, self.p, "top")
  950.     end
  951.        
  952.     if self.decoration == "underline" then
  953.         gc:drawLine(self.x, self.y+self.textH, self.x+self.textW, self.y+self.textH)
  954.     end
  955. end
  956.  
  957. function sLabel:getFocus(n)
  958.     --[[if n then
  959.          n  = n < 0 and -1 or (n > 0 and 1 or 0)
  960.      end
  961.  
  962.      if self.widget and not n then
  963.          self.widget:giveFocus()
  964.      elseif n then
  965.          self.parent:switchFocus(n)
  966.      end]] --
  967.     --return false
  968.     self.parent:switchFocus(1)
  969. end
  970.  
  971.  
  972. ------------------------------------------------------------------
  973. --                        Button Widget                         --
  974. ------------------------------------------------------------------
  975.  
  976. sButton =   class(Widget)
  977.  
  978. function sButton:init(text, action)
  979.     self.text   =   text
  980.     self.action =   action
  981.    
  982.     self.dh =   27
  983.     self.dw =   48
  984.    
  985.     self.bgColor = {248,232,170}
  986.     self.bordercolor    =   {136,136,136}
  987.     self.font   =   {"sansserif", "r", 10}
  988. end
  989.  
  990. function sButton:paint(gc)
  991.     gc:setFont(uCol(self.font))
  992.     self.ww =   gc:getStringWidth(self.text)+8
  993.     self:size()
  994.    
  995.     if self.pushed and self.forcePushed and not self.disabled then
  996.         self.y = self.y + 2
  997.     end
  998.    
  999.     if self.disabled then
  1000.         self.bgColor = {250,245,200}
  1001.     end
  1002.    
  1003.     gc:setColorRGB(unpack(self.bgColor))
  1004.        
  1005.     gc:fillRect(self.x+2, self.y+2, self.w-4, self.h-4)
  1006.     gc:setColorRGB(0,0,0)
  1007.    
  1008.     if self.disabled then gc:setColorRGB(70,70,70) end
  1009.     gc:drawString(self.text, self.x+4, self.y+4, "top")
  1010.        
  1011.     gc:setColorRGB(uCol(self.bordercolor))
  1012.     gc:fillRect(self.x + 2, self.y, self.w-4, 2)
  1013.     gc:fillRect(self.x + 2, self.y+self.h-2, self.w-4, 2)
  1014.    
  1015.     gc:fillRect(self.x, self.y+2, 1, self.h-4)
  1016.     gc:fillRect(self.x+1, self.y+1, 1, self.h-2)
  1017.     gc:fillRect(self.x+self.w-1, self.y+2, 1, self.h-4)
  1018.     gc:fillRect(self.x+self.w-2, self.y+1, 1, self.h-2)
  1019.    
  1020.     if self.hasFocus and not self.disabled then
  1021.         gc:setColorRGB(40, 148, 184)
  1022.         gc:drawRect(self.x-2, self.y-2, self.w+3, self.h+3)
  1023.         gc:drawRect(self.x-3, self.y-3, self.w+5, self.h+5)
  1024.     end
  1025. end
  1026.  
  1027.  
  1028. function sButton:mouseMove(x,y)
  1029.     local isIn = (x>self.x and x<(self.x+self.w) and y>self.y and y<(self.y+self.h))
  1030.     self.pushed = self.forcePushed and isIn
  1031.     platform.window:invalidate()
  1032. end
  1033.  
  1034. function sButton:enterKey()
  1035.     if self.action then self.action() end
  1036. end
  1037.  
  1038. function sButton:mouseDown(x,y)
  1039.     if (x>self.x and x<(self.x+self.w) and y>self.y and y<(self.y+self.h)) then
  1040.         self.pushed = true
  1041.         self.forcePushed = true
  1042.     end
  1043.     platform.window:invalidate()
  1044. end
  1045.  
  1046. function sButton:mouseUp(x,y)
  1047.     self.pushed = false
  1048.     self.forcePushed = false
  1049.     if (x>self.x and x<(self.x+self.w) and y>self.y and y<(self.y+self.h)) then
  1050.         self:enterKey()
  1051.     end
  1052.     platform.window:invalidate()
  1053. end
  1054.  
  1055.  
  1056. ------------------------------------------------------------------
  1057. --                        Screen Widget                         --
  1058. ------------------------------------------------------------------
  1059.  
  1060. sScreen = class(WWidget)
  1061.  
  1062. function sScreen:init(w, h)
  1063.     Widget.init(self)
  1064.     self.ww = w
  1065.     self.hh = h
  1066.     self.oy = 0
  1067.     self.ox = 0
  1068.     self.noloop = true
  1069. end
  1070.  
  1071. function sScreen:appended()
  1072.     self.oy = 0
  1073.     self.ox = 0
  1074. end
  1075.  
  1076. function sScreen:paint(gc)
  1077.     gc_clipRect(gc, "set", self.x, self.y, self.w, self.h)
  1078.     self.= self.x + self.ox
  1079.     self.= self.y + self.oy
  1080. end
  1081.  
  1082. function sScreen:postPaint(gc)
  1083.     gc_clipRect(gc, "reset")
  1084. end
  1085.  
  1086. function sScreen:setY(y)
  1087.     self.oy = y or self.oy
  1088. end
  1089.                        
  1090. function sScreen:setX(x)
  1091.     self.ox = x or self.ox
  1092. end
  1093.  
  1094. function sScreen:showWidget()
  1095.     local w = self:getWidget()
  1096.     if not w then print("bye") return end
  1097.     local y = self.y - self.oy
  1098.     local wy = w.y - self.oy
  1099.    
  1100.     if w.y-2 < y then
  1101.         print("Moving up")
  1102.         self:setY(-(wy-y)+4)
  1103.     elseif w.y+w.h > y+self.h then
  1104.         print("moving down")
  1105.         self:setY(-(wy-(y+self.h)+w.h+2))
  1106.     end
  1107.    
  1108.     if self.focus == 1 then
  1109.         self:setY(0)
  1110.     end
  1111. end
  1112.  
  1113. function sScreen:getFocus(n)
  1114.     if n==-1 or n==1 then
  1115.         self:stealFocus()
  1116.         self:switchFocus(n, true)
  1117.     end
  1118. end
  1119.  
  1120. function sScreen:loop(n)
  1121.     self.parent:switchFocus(n)
  1122.     self:showWidget()
  1123. end
  1124.  
  1125. function sScreen:focusChange()
  1126.     self:showWidget()
  1127. end
  1128.  
  1129. function sScreen:loseFocus(n)
  1130.     if n and ((n >= 1 and self.focus+n<=#self.widgets) or (n <= -1 and self.focus+n>=1)) then
  1131.         self:switchFocus(n)
  1132.         return -1
  1133.     else
  1134.         self:stealFocus()
  1135.     end
  1136.    
  1137. end
  1138.  
  1139.  
  1140. ----------
  1141.  
  1142.  
  1143.  
  1144. ------------------------------------------------------------------
  1145. --                       DivInput Widget                        --
  1146. ------------------------------------------------------------------
  1147.  
  1148. DivInput = class(WWidget)
  1149.  
  1150. function DivInput:init(data)
  1151.     Widget.init(self)
  1152.     self.ww = 90
  1153.     self.hh = 40
  1154.     self.data = data
  1155.     self.label = data.label
  1156.     self.topText = data.topText
  1157.     self.ansTop = data.ansTop
  1158.     self.topInput = sInput()
  1159.         self.topInput.ww = 25
  1160.         self.topInput.hh = 15
  1161.         self.topInput.placeholder = data.topPlaceholder or " ?"
  1162.         self.topInput.border = false
  1163.         self.topInput.value = self.topText or ""
  1164.         self.topInput.disabled = data.disabled
  1165.     self.bottomText = data.bottomText
  1166.     self.ansBottom = data.ansBottom
  1167.     self.bottomInput = sInput()
  1168.         self.bottomInput.ww = 25
  1169.         self.bottomInput.hh = 15
  1170.         self.bottomInput.placeholder = data.bottomPlaceholder or " ?"
  1171.         self.bottomInput.border = false
  1172.         self.bottomInput.value = self.bottomText or ""
  1173.         self.bottomInput.disabled = data.disabled
  1174.         self.bottomInput.enterKey = function() self.parent:tabKey() end -- ahem
  1175. end
  1176.  
  1177. function DivInput:appended()
  1178.     local captionLabel = sLabel(self.label)
  1179.     self:appendWidget(captionLabel, "1", "25")
  1180.     self:appendWidget(sLabel("_____"), captionLabel.w+23, "10")
  1181.     self:appendWidget(self.topInput, captionLabel.w+28, "6")
  1182.     self:appendWidget(self.bottomInput, captionLabel.w+28, "58")
  1183. end
  1184.  
  1185. function DivInput:loseFocus()
  1186.     self.bottomInput.hasFocus = false
  1187.     self.topInput.hasFocus = false
  1188.     if #self.topInput.value > 0 and #self.bottomInput.value > 0 then
  1189.         self:checkValues()
  1190.     end
  1191. end
  1192.  
  1193. function DivInput:checkValues()
  1194.     if self.topInput.value ~= self.ansTop and self.topInput.value ~= self.ansTop:reverse() then
  1195.         self.topInput.textcolor = {255,0,0} else self.topInput.textcolor = {0,0,0}
  1196.     end
  1197.     if self.bottomInput.value ~= self.ansBottom and self.bottomInput.value ~= self.ansBottom:reverse() then
  1198.         self.bottomInput.textcolor = {255,0,0} else self.bottomInput.textcolor = {0,0,0}
  1199.     end
  1200.     if (self.topInput.value == self.ansTop or self.topInput.value == self.ansTop:reverse())
  1201.        and (self.bottomInput.value == self.ansBottom or self.bottomInput.value == self.ansBottom:reverse()) then
  1202.         self:disable()
  1203.     end    
  1204. end
  1205.  
  1206. function DivInput:disable()
  1207.     self.topInput.disabled = true
  1208.     self.bottomInput.disabled = true
  1209. end
  1210.  
  1211. function DivInput:enterKey()
  1212.     if not self.topInput.hasFocus and not self.bottomInput.hasFocus then
  1213.         self.topInput:enterKey()
  1214.         return 0
  1215.     end
  1216.     if self.topInput.hasFocus then
  1217.         self.topInput:enterKey()
  1218.     else
  1219.         self.bottomInput:enterKey()
  1220.     end
  1221. end
  1222.  
  1223. function DivInput:postPaint(gc)
  1224.     if self.hasFocus then
  1225.         gc:setColorRGB(0,0,255)
  1226.         gc:drawRect(self.x, self.y, self.w, self.h)
  1227.     end
  1228. end
  1229.  
  1230.  
  1231.  
  1232.  
  1233. ------------------------------------------------------------------
  1234. --                    clickableText Widget                      --
  1235. ------------------------------------------------------------------
  1236.  
  1237. clickableText   =   class(Widget)
  1238.  
  1239. function clickableText:init(width, height, text, action)
  1240.     --self.widget   =   widget
  1241.     self.text   =   text
  1242.     self.ww     =   width
  1243.     self.action = action
  1244.    
  1245.     self.hh     =   height
  1246.     self.lim    =   false
  1247.     self.color  =   {255,255,255}
  1248.     self.shadowColor = {0,0,0}
  1249.     self.font   =   {"serif", "b", 10}
  1250.     self.p      =   "top"
  1251.    
  1252. end
  1253.  
  1254. function clickableText:paint(gc)
  1255.     gc:setFont(uCol(self.font))
  1256.    
  1257.     --gc:drawRect(self.x, self.y, self.w, self.h)
  1258.    
  1259.     --[[local text  =   ""
  1260.     local ttext
  1261.     if self.lim then
  1262.         text, self.dw   = textLim(gc, self.text, self.w)
  1263.     else
  1264.         text = self.text
  1265.     end]]
  1266.    
  1267.     gc:setColorRGB(uCol(self.shadowColor))
  1268.     gc:drawString(self.text, self.x-1, self.y+10-1, self.p)
  1269.     gc:setColorRGB(uCol(self.color))
  1270.     gc:drawString(self.text, self.x, self.y+10, self.p)
  1271. end
  1272.  
  1273. function clickableText:getFocus(n)
  1274.     if n then
  1275.         n   = n < 0 and -1 or (n > 0 and 1 or 0)
  1276.     end
  1277.    
  1278.     if self.widget and not n then
  1279.         self.widget:giveFocus()
  1280.     elseif n then
  1281.         self.parent:switchFocus(n)
  1282.     end
  1283. end
  1284.  
  1285. function clickableText:mouseUp()
  1286.     if self.action then self.action() end
  1287. end
  1288.  
  1289.  
  1290.  
  1291. ------------------------------------------------------------------
  1292. --                       Pie Chart Widget                       --
  1293. ------------------------------------------------------------------
  1294.  
  1295. sPieChart   = class(WWidget)
  1296.  
  1297. function sPieChart:init(width, height, data, options)
  1298.     Widget.init(self)
  1299.     self.options = options
  1300.     self.ww = width
  1301.     self.hh = height
  1302.     self.data = data
  1303.    
  1304.     self.caption = data.caption
  1305.     self.borderColor = options.borderColor or {0,0,0}
  1306.     self.bgColor = options.bgColor or {255, 255, 255}
  1307.    
  1308.     self.show3d = self.options.show3d
  1309.     self.showNames = self.options.showNames
  1310.    
  1311.     self.sumOfValues = self:getSumOfValues()
  1312.     self:calculatePercentages()
  1313.     self:calculateAngles()
  1314.    
  1315. end
  1316.  
  1317.  
  1318. function sPieChart:appended()
  1319.     --override--
  1320.     self.ww = self.h
  1321.     self.w = self.h
  1322.    
  1323.     self.radius = math.floor(self.w/2)
  1324.    
  1325.     angleSumSoFar = 0
  1326.     for i,v in ipairs(self.data) do
  1327.         if self.showNames then
  1328.             sCaption = clickableText("30", "35", "       ", function() self:selectNumber(i) end)
  1329.             -- to redo :( (or see with lua script at 1.2)
  1330.             self:appendWidget(sCaption, self.x+self.w/4.7+.6*(self.w/2*math.cos(3.14/180*(90-angleSumSoFar-(v.angle/2)))), self.y+self.h/3+.65*(self.h/2*math.sin(3.14/180*(90-angleSumSoFar-(v.angle/2)-180))))
  1331.         end
  1332.         angleSumSoFar = angleSumSoFar + v.angle
  1333.     end
  1334.        
  1335. end
  1336.  
  1337. function sPieChart:selectNumber(nbr)
  1338.     -- do whatever you want
  1339. end
  1340.  
  1341. function sPieChart:loseFocus()
  1342.     self:selectNumber(-1)
  1343. end
  1344.  
  1345. function sPieChart:getSumOfValues()
  1346.     local sum = 0
  1347.     for _,v in ipairs(self.data) do
  1348.         sum = sum + v.value
  1349.     end
  1350.     return sum
  1351. end
  1352.  
  1353. function sPieChart:calculatePercentages()
  1354.     for _,v in ipairs(self.data) do
  1355.         v.percentage = math.round(v.value*100/self.sumOfValues,2)
  1356.     end
  1357. end
  1358.  
  1359. function sPieChart:calculateAngles()
  1360.     for _,v in ipairs(self.data) do
  1361.         v.angle = math.round(v.percentage*90/25,2) -- 25% is 90 deg
  1362.     end
  1363. end
  1364.  
  1365. function sPieChart:paint(gc)
  1366.    
  1367.     if self.hasFocus then
  1368.         gc:setColorRGB(150, 150, 255)
  1369.         gc:drawArc(self.x-2, self.y-2, self.w+3, self.h+3, 0, 360)
  1370.          if self.show3d then gc:drawArc(self.x-2, self.y+7, self.w+4, self.h+2, 0, 360) end
  1371.     end
  1372.    
  1373.     if self.show3d then
  1374.         local angleSumSoFar = 0
  1375.         for i,v in ipairs(self.data) do
  1376.             gc:setColorRGB(.8*v.color[1], .8*v.color[2], .8*v.color[3])
  1377.             gc:fillArc(self.x-1, self.y+8, self.w+2, self.h, 90-angleSumSoFar-(v.angle)-.3, (v.angle))
  1378.             gc:fillArc(self.x, self.y+8, self.w+2, self.h, 90-angleSumSoFar-(v.angle)-.3, (v.angle))
  1379.             gc:fillArc(self.x, self.y+5, self.w+2, self.h, 90-angleSumSoFar-(v.angle)-.3, (v.angle))
  1380.             angleSumSoFar = angleSumSoFar + v.angle
  1381.         end
  1382.         gc:setColorRGB(unpack(self.borderColor))
  1383.         gc:drawArc(self.x, self.y+8, self.w, self.h, 0, 360)
  1384.     end
  1385.    
  1386.     gc:drawArc(self.x-1, self.y-1, self.w+2, self.h+2, 0, 360)
  1387.     gc:drawArc(self.x, self.y, self.w, self.h, 0, 360)
  1388.  
  1389.     local angleSumSoFar = 0
  1390.     for i,v in ipairs(self.data) do
  1391.         gc:setColorRGB(unpack(v.color))
  1392.         gc:fillArc(self.x, self.y, self.w, self.h, 90-angleSumSoFar-(v.angle)-.3, (v.angle))
  1393.         v.startAngle = 90-angleSumSoFar-(v.angle)-.3
  1394.         v.endAngle = v.angle
  1395.         gc:fillArc(self.x, self.y, self.w, self.h, 90-angleSumSoFar-(v.angle+1), (v.angle))
  1396.         angleSumSoFar = angleSumSoFar + v.angle
  1397.     end
  1398.    
  1399.     angleSumSoFar = 0
  1400.     for i,v in ipairs(self.data) do
  1401.         gc:setColorRGB(75,75,75)
  1402.         gc:drawLine(self.x+self.w/2, self.y+self.h/2, self.x+self.w/2+self.w/2*math.cos(3.14/180*(90-angleSumSoFar-(v.angle))), self.y+self.h/2+self.h/2*math.sin(3.14/180*(90-angleSumSoFar-(v.angle)-180)))
  1403.         if v.highlight then
  1404.             gc:setPen("medium", "smooth")
  1405.             gc:setColorRGB(0,0,0)
  1406.             gc:drawArc(self.x, self.y, self.w, self.h, 90-angleSumSoFar-(v.angle)+1, v.angle-2)
  1407.             gc:setPen("thin", "smooth")
  1408.         end
  1409.         if self.showNames then -- meh, to redo ?
  1410.             gc:setFont("serif", "b", 12)
  1411.             gc:setColorRGB(0,0,0)
  1412.             gc:drawString(v.name, self.x-1+self.w/3+.6*(self.w/2*math.cos(3.14/180*(90-angleSumSoFar-(v.angle/2)))), self.y-1+self.h/1.8+.65*(self.h/2*math.sin(3.14/180*(90-angleSumSoFar-(v.angle/2)-180))))
  1413.             gc:setColorRGB(255,255,255)
  1414.             gc:drawString(v.name, self.x+self.w/3+.6*(self.w/2*math.cos(3.14/180*(90-angleSumSoFar-(v.angle/2)))), self.y+self.h/1.8+.65*(self.h/2*math.sin(3.14/180*(90-angleSumSoFar-(v.angle/2)-180))))
  1415.         end
  1416.         angleSumSoFar = angleSumSoFar + v.angle
  1417.     end
  1418. end
  1419.  
  1420. --[[
  1421. function CrossProduct(vect1, vect2)
  1422.     return { x= vect1.y*vect2.z-vect1.z*vect2.y, y = vect1.z*vect2.x-vect1.x*vect2.z, z = vect1.x*vect2.y-vect1.y*vect2.x }
  1423. end
  1424.  
  1425. function DotProduct(vect1, vect2)
  1426.     return vect1.x*vect2.x+vect1.y*vect2.y+vect1.z*vect2.z
  1427. end
  1428.  
  1429. function sPieChart:SameSide(p1,p2, a,b)
  1430.     cp1 = CrossProduct({x = b.x-a.x, y = b.y-a.y, z = 0}, {x = p1.x-a.x, y = p1.y-a.y, z = 0})
  1431.     cp2 = CrossProduct({x = b.x-a.x, y = b.y-a.y, z = 0}, {x = p2.x-a.x, y = p2.y-a.y, z = 0})
  1432.     return DotProduct( {x = cp1.x, y = cp1.y, z = cp1.z}, {x = cp2.x, y = cp2.y, z = cp2.z} ) >= 0
  1433. end
  1434.  
  1435. function sPieChart:isPointInTriangle(p, a,b,c)
  1436.     return self:SameSide(p,a, b,c) and self:SameSide(p,b, a,c) and self:SameSide(p,c, a,b)
  1437. end
  1438.  
  1439. print( sPieChart:isPointInTriangle( {x=1, y=1, z=0}, {x=0, y=0, z=0},{x=1, y=3, z=0},{x=3, y=1, z=0} ) )
  1440.  ]]-- not needed anyway
  1441.  
  1442. function sPieChart:distanceBetween(p1,p2)
  1443.     return math.sqrt((p2.x-p1.x)^2+(p2.y-p1.y)^2)
  1444. end
  1445.  
  1446. function sPieChart:mouseUpDISABLED(xx,yy) -- p is {x,y}
  1447.     local p = {x=xx, y=yy, angle=math.abs(180/3.142*math.atan((yy-self.y)/(xx-self.x)))}
  1448.     local center = {x=self.x+self.radius, y=self.y+self.radius}
  1449.        
  1450.     local angleSumSoFar = 0
  1451.     local tmp = 0
  1452.     for i,v in ipairs(self.data) do
  1453.  
  1454.         -- check for each v : ((distance from  p to center) <= radius) AND (startAngle < arctan(y/x) < endAngle)
  1455.        
  1456.         --print("part "..i, self:distanceBetween(p,center)<=self.radius , math.abs(90-angleSumSoFar-(v.angle+1))> p.angle , p.angle < math.abs((v.angle)) )
  1457.         --print("------")
  1458.        
  1459.         if self:distanceBetween(p,center)<=self.radius and math.abs(v.startAngle) < p.angle and p.angle < math.abs(v.angle) then
  1460.                --print(i)
  1461.                tmp = i
  1462.                --break
  1463.         else
  1464.            v.highlight = false
  1465.         end
  1466.          
  1467.         angleSumSoFar = angleSumSoFar + v.angle
  1468.     end
  1469.     --if tmp > 0 then self.data[tmp].highlight = true end
  1470. end
  1471.  
  1472.  
  1473.  
  1474.  
  1475.  
  1476. ------------------------------------------------------------------
  1477. --                        Slider Widget                         --
  1478. ------------------------------------------------------------------
  1479.  
  1480. sSlider = class(Widget)
  1481.  
  1482. function sSlider:init(width, height, options)
  1483.     self.options = options
  1484.     self.ww = width
  1485.     self.hh = height
  1486.     self.min = options.min or 0
  1487.     self.max = options.max or 100
  1488.     self.step = options.step or ((self.max-self.min)/10)
  1489.     --if self.min > self.max then self.min, self.max = self.max, self.min end
  1490.     self.reverse = self.min<self.max
  1491.     self.showGraduations = options.showGraduations or true
  1492.     self.showBounds = options.showBounds or false
  1493.     self.defaultValue = options.defaultValue or math.ceil((self.max-self.min)/2)
  1494.     self.internalValue = self.defaultValue
  1495.     self.borderColor = options.borderColor or {40, 148, 184}
  1496.     self.bgColor = options.bgColor or {255, 255, 255}
  1497.     if not options.line then options.line = {} end
  1498.     self.line = { thickness = options.line.thickness or 5,
  1499.                   bgColor = options.line.bgColor or {200,200,200},
  1500.                   borderColor = options.line.borderColor or {0,0,0} }
  1501.     self.cursor = {}
  1502.     self.value = self.max-self.internalValue
  1503.     self.pValue = math.ceil(self.value*100/self.max)
  1504.  
  1505.     -- ....
  1506. end
  1507.  
  1508. function sSlider:value2px(value)
  1509.     return self.orientation == "vertical" and math.floor((self.y+0.94*value/(self.max-self.min)*(self.h))-3) or math.floor((self.x+(0.94*value)/(self.max-self.min)*(self.w))-3)
  1510. end
  1511.  
  1512. function sSlider:px2value(px)
  1513.     return self.orientation == "vertical" and math.floor(((px-self.y)*(self.max-self.min))/(self.h)) or math.floor(((px-self.x)*(self.max-self.min))/(self.w))
  1514. end
  1515.  
  1516. function sSlider:appended()
  1517.     self.orientation = (tonumber(self.hh) >= tonumber(self.ww)) and "vertical" or "horizontal"
  1518.     self.graduations = self.options.graduations or (self.orientation == "vertical" and math.ceil(self.h/30) or math.ceil(self.w/20) )
  1519.     self.graduationsStep = self.options.graduationsStep or (self.max-self.min)/(self.graduations+2)
  1520.     self:updateCursor()
  1521. end
  1522.  
  1523. function sSlider:updateCursor()
  1524.     self.cursor = { x = (self.orientation == "vertical") and self.x+(self.w-self.line.thickness)/2-2 or self:value2px(self.internalValue),
  1525.                     y = (self.orientation == "vertical") and self:value2px(self.internalValue) or self.y+(self.h-self.line.thickness)/2-2,
  1526.                     radius=8 }
  1527.     self.value = self.orientation == "vertical" and self.max-self.internalValue or self.internalValue
  1528.     self.pValue = math.ceil(self.value*100/self.max)
  1529.     self.parent:update()
  1530. end
  1531.  
  1532. function sSlider:updateValue()
  1533.     self.internalValue = (self.orientation == "vertical") and self:px2value(self.cursor.y) or self:px2value(self.cursor.x)
  1534.     if self.internalValue < self.min then self.internalValue = self.min end
  1535.     if self.internalValue > self.max then self.internalValue = self.max end
  1536. end
  1537.  
  1538. function sSlider:paint(gc)
  1539.     gc:setColorRGB(unpack(self.bgColor))
  1540.     --gc:fillRect(self.x, self.y, self.w, self.h)
  1541.    
  1542.     gc:setColorRGB(unpack(self.line.bgColor))
  1543.     if self.orientation == "vertical" then
  1544.         gc:fillRect(self.x+(self.w-self.line.thickness)/2, self.y, self.line.thickness, self.h)
  1545.     else
  1546.         gc:fillRect(self.x, self.y+(self.h-self.line.thickness)/2, self.w, self.line.thickness)
  1547.     end
  1548.    
  1549.     gc:setColorRGB(0,0,0)
  1550.     if self.orientation == "vertical" then
  1551.         gc:fillRect(self.x+self.w/3, self.y-1, self.w/3.2, 2)
  1552.         gc:fillRect(self.x+self.w/3, self.y+self.h-1, self.w/3.2, 2)
  1553.         if self.showBounds then
  1554.             gc:drawString(self.max,self.x+(self.w+self.line.thickness+8)/2, self.y, "middle")
  1555.             gc:drawString(self.min,self.x+(self.w+self.line.thickness+8)/2, self.y+self.h-5, "middle")
  1556.         end
  1557.     else
  1558.         gc:fillRect(self.x-1, self.y+self.h/4-1, 2, self.h/2)
  1559.         gc:fillRect(self.x+self.w-1, self.y+self.h/4, 2, self.h/2)
  1560.         if self.showBounds then
  1561.             gc:drawString(self.min, self.x, self.y, "middle")
  1562.             gc:drawString(self.max, self.x+self.w-10, self.y, "middle")
  1563.         end
  1564.     end
  1565.  
  1566.     fillCircle(gc,self.cursor.x,self.cursor.y, 8)
  1567.    
  1568.     gc:setColorRGB(unpack(self.borderColor))
  1569.     drawCircle(gc,self.cursor.x,self.cursor.y, 8)
  1570.     if self.hasFocus then
  1571.         gc:setColorRGB(unpack(self.borderColor))
  1572.         fillCircle(gc,self.cursor.x+3,self.cursor.y+3, 2.5)
  1573.     end
  1574. end
  1575.  
  1576. function sSlider:grabDown(x,y)
  1577.     print("grabDown")
  1578.     self.isGrabbing = not self.isGrabbing
  1579. end
  1580.  
  1581. function sSlider:mouseUp(x,y)
  1582.     cursor.set("default")
  1583.     self.isGrabbing = false
  1584. end
  1585.  
  1586. function sSlider:mouseDown(x,y)
  1587.     if math.abs(self.cursor.x+self.cursor.radius/2-x) <= self.cursor.radius and math.abs(self.cursor.y+self.cursor.radius/2-y) <= self.cursor.radius then
  1588.         self.isGrabbing = true
  1589.     end
  1590. end
  1591.  
  1592. function sSlider:mouseMove(x,y)
  1593.     if self.isGrabbing then
  1594.         cursor.set("drag grab")
  1595.         if self.orientation == "vertical" then
  1596.             self.cursor.y = y+2
  1597.             self:updateValue()
  1598.         else
  1599.             self.cursor.x = x+2
  1600.             self:updateValue()
  1601.         end
  1602.         self:updateCursor()
  1603.     else
  1604.         if math.abs(self.cursor.x+self.cursor.radius/2-x) <= 1.6*self.cursor.radius/2 and math.abs(self.cursor.y+self.cursor.radius/2-y) <= 1.6*self.cursor.radius/2 then
  1605.             cursor.set("hand pointer")
  1606.         else
  1607.             cursor.set("default")
  1608.         end
  1609.     end
  1610. end
  1611.  
  1612.  
  1613.  
  1614.  
  1615.  
  1616. ------------------------------------------------------
  1617. --                 s2DArray Widget                  --
  1618. ------------------------------------------------------
  1619.  
  1620. s2DArray = class(WWidget)
  1621.  
  1622. function s2DArray:init(width, height, data)
  1623.     Widget.init(self)
  1624.     self.width  = width
  1625.     self.ww = width
  1626.     self.height = height
  1627.     self.hh = height
  1628.     self.data = data or {}
  1629.     self.columns = (#self.data > 0) and #(self.data[1]) or 0
  1630.     self.rows = #self.data or 0
  1631.     --setmetatable(self.data, { __index = function() return "" end })
  1632.     self.content = {}
  1633.     self.totalAttempts = 0
  1634.     self.hasFinished = false
  1635.     self.centeredText = true
  1636.     self.totalAnswers = self.data.totalAnswers or 0
  1637.     self.correctAnswers = 0
  1638.     self.maxAttempts = 5
  1639. end
  1640.  
  1641. function s2DArray:appended()
  1642.     for j=1, self.rows do
  1643.         self.content[j] = {}
  1644.         for i=1, self.columns do
  1645.             local theInput = sInput()
  1646.             theInput.showBorder = true
  1647.             theInput.ww = self.w/self.columns
  1648.             theInput.hh = self.h/self.rows
  1649.             theInput.id = {i,j}
  1650.             theInput.centeredText = self.centeredText or false -- lulz bool logic
  1651.             theInput.value = self.data[j][i].text or ""
  1652.             theInput.placeholder = self.data[j][i].placeholder or ""
  1653.             theInput.font[2] = (self.data[j][i].isHeader or self.data[j][i].isEditable) and "b" or "r" -- bold or regular
  1654.             theInput.number = self.data[j][i].numbersOnly or false
  1655.             theInput.disabled = not self.data[j][i].isEditable
  1656.             function theInput:enterKey()
  1657.                 self.parent:checkContent(self.id[2], self.id[1])
  1658.                 self.parent:switchFocus(2)--self:getNextEditableCell(i,j))
  1659.             end
  1660.             function theInput:arrowKey(arrw)
  1661.                 if not self.disabled then
  1662.                     self.parent:checkContent(self.id[2], self.id[1])
  1663.                     if arrw == "up" then
  1664.                         if self.parent.content[self.id[2]-1] and not self.parent.content[self.id[2]-1][self.id[1]].disabled then
  1665.                             self.parent:switchFocus(-2)
  1666.                         end
  1667.                     elseif arrw == "down" then
  1668.                         if self.parent.content[self.id[2]+1] and not self.parent.content[self.id[2]+1][self.id[1]].disabled then
  1669.                             self.parent:switchFocus(2)
  1670.                         end                    
  1671.                     elseif arrw == "left" then
  1672.                         if self.parent.content[self.id[2]][self.id[1]-1] and not self.parent.content[self.id[2]][self.id[1]-1].disabled then
  1673.                             self.parent:switchFocus(-1)
  1674.                         end                    
  1675.                     elseif arrw == "right" then
  1676.                         if self.parent.content[self.id[2]][self.id[1]+1] and not self.parent.content[self.id[2]][self.id[1]+1].disabled then
  1677.                             self.parent:switchFocus(1)
  1678.                         end                    
  1679.                     end
  1680.                 end
  1681.             end
  1682.             self.content[j][i] = theInput
  1683.             self:appendWidget(self.content[j][i], (self.w/self.columns)*(i-1), (self.h/self.rows)*(j-1))
  1684.         end
  1685.     end
  1686. end
  1687.  
  1688. function s2DArray:getNextEditableCell(col, row)
  1689.    
  1690.     return 0
  1691. end
  1692.  
  1693. function s2DArray:displayExpected()
  1694.     for j=1, self.rows do
  1695.         for i=1, self.columns do
  1696.             self.content[j][i].disabled = true
  1697.             self.content[j][i].value = self.data[j][i].answer or self.content[j][i].value
  1698.         end
  1699.     end
  1700.     print("Disabled inputs + showing answers")
  1701. end
  1702.  
  1703. function s2DArray:paint(gc)
  1704.     if self.hasFocus then    
  1705.         gc:setColorRGB(40, 148, 184)
  1706.         gc:drawRect(self.x-1, self.y-1, self.w+3, self.h+2)
  1707.     end
  1708. end
  1709.  
  1710. function s2DArray:loseFocus()
  1711.     self.hasFocus = false -- useless (works without)
  1712.     for j=1, self.rows do
  1713.         for i=1, self.columns do
  1714.             self.content[j][i].hasFocus = false
  1715.         end
  1716.     end
  1717. end
  1718.  
  1719. function s2DArray:checkContent(row, col)
  1720.     local expectedValue = self.data[row][col].answer or ""
  1721.     local otherExpectedValue = self.data[row][col].optAnswer or ""
  1722.     local theInput = self.content[row][col]
  1723.     --print("checking content at R".. row.."C"..col.." : is ", theInput.value or "", " == ", expectedValue, " ?  ", ((self.content[row][col].value or "") == expectedValue))
  1724.     local isGood = (theInput.value == expectedValue) or (theInput.value == otherExpectedValue)
  1725.     if not theInput.disabled and not self.hasFinished and not (self.totalAttempts > self.maxAttempts) and #theInput.value>0 then
  1726.         if not isGood then
  1727.             print("Wrong !!")
  1728.             self.content[row][col].bgcolor = {255,0,0}
  1729.             self.totalAttempts = self.totalAttempts + 1
  1730.         else
  1731.             print("Correct !!")
  1732.             self.content[row][col].bgcolor = {0,255,0}
  1733.             self.content[row][col].disabled = true
  1734.             self.content[row][col].value = self.data[row][col].answer or self.content[row][col].value
  1735.             self.correctAnswers = self.correctAnswers + 1
  1736.         end
  1737.         if self.totalAttempts == self.maxAttempts or self.correctAnswers == self.totalAnswers then
  1738.             self.hasFinished = true
  1739.             self:displayExpected()
  1740.         end
  1741.     end
  1742. end
  1743.  
  1744.  
  1745.  
  1746. ----------
  1747.  
  1748.  
  1749. function on.timer() current_screen():timer() screenRefresh() end
  1750. function on.arrowKey(arrw) current_screen():arrowKey(arrw) screenRefresh() end
  1751. function on.enterKey() current_screen():enterKey() screenRefresh() end
  1752. function on.escapeKey() current_screen():escapeKey() screenRefresh() end
  1753. function on.tabKey() current_screen():tabKey() screenRefresh() end
  1754. function on.backtabKey() current_screen():backtabKey() screenRefresh() end
  1755. function on.clearKey() current_screen():clearKey() screenRefresh() end
  1756. function on.charIn(ch) current_screen():charIn(ch) screenRefresh() end
  1757. function on.backspaceKey() current_screen():backspaceKey() screenRefresh() end
  1758. function on.mouseDown(x, y) current_screen():mouseDown(x, y) screenRefresh() end
  1759. function on.mouseUp(x, y) current_screen():mouseUp(x, y) screenRefresh()  end
  1760. function on.mouseMove(x, y) current_screen():mouseMove(x, y) screenRefresh() end
  1761. function on.grabDown(x, y) current_screen():grabDown(x, y) screenRefresh() end
  1762.  
  1763.  
  1764.  
  1765. ------------------------------
  1766. ---  ETK Library finished  ---
  1767. ------------------------------
  1768.  
  1769.  
  1770. function showPopup()
  1771.  
  1772.     StatsWindow = Dialog("Popup window", 150, 20, 268, 164)
  1773.    
  1774.     local StatsStr  = [[Hello world
  1775.    
  1776. Put any text here...
  1777. any text here...
  1778. any text here...
  1779. ]]
  1780.    
  1781.     local StatsOkButton = sButton("OK")
  1782.    
  1783.     for i, line in ipairs(StatsStr:split("\n")) do
  1784.         local StatsText = sLabel(line)
  1785.         StatsWindow:appendWidget(StatsText, 10, 27 + i*14-12)
  1786.     end
  1787.    
  1788.     StatsWindow:appendWidget(StatsOkButton,-10,-5)
  1789.    
  1790.     function StatsWindow:postPaint(gc)
  1791.         nativeBar(gc, self, self.h-40)
  1792.         on.help = function() return 0 end
  1793.     end
  1794.    
  1795.     StatsOkButton:giveFocus()
  1796.    
  1797.     function StatsWindow:escapeKey()
  1798.         StatsOkButton:action()
  1799.     end
  1800.    
  1801.     function StatsWindow:arrowKey(arrw)
  1802.         if arrw == "up" then
  1803.             self:backtabKey()
  1804.         elseif arrw == "down" then
  1805.             self:tabKey()
  1806.         end
  1807.     end
  1808.    
  1809.     function StatsOkButton:action()
  1810.         remove_screen(StatsWindow)
  1811.     end
  1812.    
  1813.     push_screen(StatsWindow)
  1814.  
  1815. end
  1816.  
  1817. -----------------
  1818. ------Main:------
  1819. -----------------
  1820.  
  1821. Main = WScreen()
  1822.  
  1823. Main.initTimer = true
  1824.  
  1825. Main.divInputs = {
  1826.     {label = "sin(A) =", ansTop = "BC", ansBottom="AC", topText = "BC", bottomText="AC", disabled=true},
  1827.     {label = "cos(A) =", ansTop = "AB", ansBottom="AC"}
  1828.  }
  1829.  
  1830. Main.pieChartData = {
  1831.         { name="Cycle", value=12, color={0,0,230} },
  1832.         { name="Bus", value=16, color={250,0,0} },
  1833.         { name="Taxi", value=8, color={0,200,0} },
  1834.         { name="Walk", value=8, color={200,0,180} },
  1835.         { name=" Car", value=4, color={115,115,250} },
  1836.         caption="students",
  1837.         showNames = true
  1838.     }
  1839.  
  1840. Main.arrayData =
  1841.     {
  1842.         { { text="Wages", isHeader=true }, { text="50-100" }, { text="100-150" }},
  1843.         { { text="Freq", isHeader=true }, { placeholder=" ? ", isEditable=true, answer="5", numbersOnly=true }, { placeholder=" ? ", isEditable=true, answer="4", numbersOnly=true }},
  1844.         totalAnswers = 3
  1845.     }
  1846.  
  1847. function Main:checkValue(obj, ans)
  1848.     if #obj.value > 0 and not obj.disabled then
  1849.         obj.tries = obj.tries and (obj.tries + 1) or 1
  1850.         if obj.value == ans then
  1851.             obj.disabled = true
  1852.         else
  1853.             if obj.tries > 1 then
  1854.                 obj.value = ans
  1855.                 obj.disabled = true
  1856.             end
  1857.         end
  1858.     end
  1859. end
  1860.  
  1861. function Main:setup()
  1862.     self.lbl1 = sLabel("        +  5  =  5")
  1863.     self.inp1 = sInput(function() Main:checkValue(self.inp1, "0") end)
  1864.     self.inp1.value = ""    self.inp1.number = true
  1865.  
  1866.     self.sliderLabel = sLabel("Slider :", {style="b", decoration="underline"} )
  1867.  
  1868.     self:appendWidget(self.sliderLabel, 5, 0)
  1869.     self:appendWidget(sLabel("Italic Underline", {style="i", decoration="underline"}), "33", 0)
  1870.     self:appendWidget(sLabel("A Bold Text", {style="b"}), -70, 0)
  1871.    
  1872.     self:appendWidget(sLabel("Standard Input :", {style="b", decoration="underline"} ), 5, "22")
  1873.     self:appendWidget(self.lbl1, "2", "34")
  1874.     self:appendWidget(self.inp1, "2", "34")
  1875.    
  1876.     local popupButton = sButton("Button")
  1877.     function popupButton:action() showPopup() end
  1878.     self:appendWidget(popupButton, "45", "83")
  1879.  
  1880.     local disabledButton = sButton("Disabled Button")
  1881.     disabledButton.disabled = true
  1882.     self:appendWidget(disabledButton, "65", "83")
  1883.    
  1884.     self:appendWidget(sLabel("Pie Chart :", {style="b", decoration="underline"} ), "42", "18")
  1885.     self.thePieChart1 = sPieChart( "38", "38", self.pieChartData, {show3d = false, showNames = true} )
  1886.     self:appendWidget(self.thePieChart1, "68", "12")
  1887.  
  1888.     self:appendWidget(sLabel("Fraction Inputs :", {style="b", decoration="underline"} ), 5, "48")
  1889.     self:appendWidget(DivInput(Main.divInputs[1]), "2", "58")
  1890.     self:appendWidget(DivInput(Main.divInputs[2]), "2", "78")
  1891.    
  1892.     self:appendWidget(sLabel("Array Inputs :", {style="b", decoration="underline"} ), "42", "48")
  1893.     local arrayInfo = s2DArray("59", "16", self.arrayData)
  1894.     self:appendWidget(arrayInfo, "40", "60")
  1895.    
  1896.     self.theSlider = sSlider(80, 20, {min = 0, max = 255, showBounds=false} )  
  1897.     self:appendWidget(self.theSlider, 5, "10")
  1898. end
  1899.  
  1900. function Main:paint(gc)
  1901.     -- extra things you want to draw, before the widgets.
  1902. end
  1903.  
  1904. function Main:postPaint(gc)
  1905.     -- extra things you want to draw, after the widgets.
  1906. end
  1907.  
  1908. function Main:resize(x,y)
  1909.     Main.initTimer = true
  1910.     timer.start(0.1)
  1911. end
  1912.  
  1913. function Main:timer(ch)
  1914.     if self.initTimer then
  1915.         timer.stop()
  1916.         self.initTimer = false    
  1917.         self:cleanWidgets()
  1918.         self:setup()
  1919.     end
  1920. end
  1921.  
  1922. function Main:update()
  1923.     self.sliderLabel.xx = self.theSlider.pValue
  1924.     self:invalidate()
  1925. end
  1926.  
  1927. Main:setup()
  1928.  
  1929.  
  1930. ----------------------
  1931. ---  Other events  ---
  1932. ----------------------
  1933.  
  1934. function on.construction()
  1935.  
  1936. end
  1937.  
  1938. function on.paint(gc)
  1939.     for _, screen in pairs(Screens) do
  1940.         screen:draw(gc)
  1941.     end
  1942. end
  1943.  
  1944. function on.deactivate()
  1945.     activated = false
  1946. end
  1947.  
  1948. function on.activate()
  1949.     activated = true
  1950. end
  1951.  
  1952. function on.resize(x, y)
  1953.     -- Global Ratio Constants for On-Calc (shouldn't be used often though...)
  1954.     kXRatio = x / 318
  1955.     kYRatio = y / 212
  1956.     kXSize = x
  1957.     kYSize = y
  1958.     for _,screen in pairs(Screens) do
  1959.         screen:resize(x, y)
  1960.     end
  1961.     platform.window:invalidate() -- redraw everything
  1962. end
  1963.  
  1964.  
  1965. -----------------
  1966. -----Start !-----
  1967. -----------------
  1968.  
  1969. push_screen(Main)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement