Cider -- interface builder / code generator

Antonio,

Thanks for the files. i added them as tabs “JSON” and DropBox."

I will admit that I am not experienced in LUA, but I am learning.

However, I had to prepend “JSON:” to “encode” and “decode” in JSON (lines 69, 93, 125, 187, and 269) to apparently make them global so that main could find them.

Let me know if there is a better way.

Now, Load and Save work perfectly!

Thanks very much for the help.

Bob

Yeah, I have an update to JSON that basically added those in and called the non-prepended versions. I haven’t updated the gist.

I want to allow load/save to ask for a screen name and save versions os screens, so we have more than one screen cached.

I had thought of having global versions of encode and decode. That way the local functions could be called from the internal places.

I just added those and it continues to work well.

Thanks again.

Bob

Yeah, I left the global s for the same reason, and added the class decorators so that different coding styles could be accommodated. Cleaner looking code if it’s in the class, in my opinion.

As I am implementing selection and highlighting for the TextBox control it would really be great if I could access the iPad’s clipboard. Does anybody know if there is a way to write to / read from the clipboard in Codea? Otherwise I’m stuck with just cut and paste within an application. Thanks.

No clipboard. You can emulate it though, with a saveGlobalData() call. Only would work in LUA, until you decide to compile an XCode app, then you can get true cut/paste.

Is the work you are doing something to roll into Cider?

@aciolino, yes, I have selection, highlighting and cut, copy, paste functionality for the TextBox to be rolled into Cider (almost done). But before I finished I wanted to explore the clipboard because that would be something that users would expect. I guess I’ll make it just local to the application and leave it at that. What’s the best way for me to make the code available to you?

Make a Gist or post it here? Or email it to me…

Another little control. This one currently can’t be set by touch, but is kind of keen for displaying values.


Dial = class(Control)

function Dial:init(t, left, bottom, right, top, min, max, val)
    Control.init(self, t, left, bottom, right, top)
    self.controlName = "Dial"
    self.min = min
    self.max = max
    self.val = val
    self.fontSize = 10
    self.hotColor = color(0, 23, 255, 255)
end

function Dial:draw()
    local x, w, h
    pushStyle()
    pushMatrix()
    fontSize(self.fontSize)
    strokeWidth(3)
    stroke(self.foreground)
    fill(self.background)
    noStroke()
    translate(self:midX(), self:midY())
    ellipse(0, 0, self:width())
    fill(self.highlight)
    ellipse(0, 0, self:width() - 10)
    fill(self.hotColor)
    w, h = textSize(self.text)
    text(self.text, 0, -h-5)
    strokeWidth(2)
    rotate(180)
    strokeWidth(3)
    for i=0,10 do
        rotate(-30)
        line(0, self:width() / 2 - 20, 0, self:width() / 2 - 10)
        x = (self.max-self.min) / 10 * i
        fill(self.foreground)
        text(x, 0, self:width() / 2 - 30)
    end
    fill(self.background)
    rotate(-30)
    ellipse(0, self:width() / 2 - 15, 10)
    strokeWidth(4)
    x = (self.val / (self.max-self.min))  * 300 + 30
    rotate(-x)
    line(0, 0, 0, self:width() / 2 - 20)
    strokeWidth(1)
    fill(self.hotColor)
    ellipse(0, self:width() / 2 - 20, 10)
    fill(self.foreground)
    ellipse(0, 0, 20)
    popMatrix()
    fill(255, 255, 255, 40)
    noStroke()
    ellipse(self:midX() - 10, self:midY() + 15, self:width() - 30)
    popStyle()
end

Try dropping one of these into the Cider controls Main using

dialTest = Dial("Dial", 500, HEIGHT - 490, 650, HEIGHT - 340, 0, 100, sldTest.val)

Then change the touch for sldTest to look like

    if sldTest:touched(touch) then
        dialTest.val = sldTest.val
    end

Thanks Mark. I’m embedding it into CiderControls now and making a few adjusments for things like callback.

I’ll update the GIST in a little while.

Thanks, I made some small changes to the code above and re-posted, just for the sake of cleaning up appearance a bit.

What do you think about giving each control an “AutoSave” status, that would allow them to save their value to a local string each time the value is changed?

not sure if we want a control to have that on each change() event - the lifetime of a control shouldn’t be to persist data. The lifetime of a form, though…that’s different story. It’s the responsibility of the application to store inforamtion, I wouldn’t delegate that to each control.

We’re venturing into the discussion of persisting data records, I think.

All that said, we can extend Control() with Save and Load functions to enable all controls to have a persistence values.

@aciolino I’m not thinking so much of saving form data in this case as I am persisting application settings between sessions.

For saving form data, I think there needs to be a simple record-manager class.

A peek at the Dial and Doughnut controls

I suppose these are really “controls,” but more gauges. Still it’s fun to watch them at work.

Dial was nice; it’s integrated in Cider, which I will update later. I don’t know about doughnut; is that another one you’d like to get integrated?

Yes, these are more reporting gauges, though I did integrate touch controls (very sloppy) into Dial. I used touch() and only checked the X values for min/max and multiplied by dial’s max value.

I really waned to make it so I “rotate” through the numbers, but my math isn’t good enough to get it right.

@Mark, when do you want to send me the updated TextBox?

@Mark, re: a record manager class, see http://twolivesleft.com/Codea/Talk/discussion/1930/sqllite-or-any-database-planned-in-the-futures#Item_1. I opened the discussion, but NO ONE has even touched it. Looks like we need to roll our own.

I also looked around to any LUA-based database stuff. THe ones I found all connect to SQLLite or are thin-wrappers to actual RDBMS’es. I found one that claimed it was “pure lua”, but it was a Lua-wrapper to Pascal (!) code.

No luck so far. I think I have to write a simple one (No joins :slight_smile: ) that can understand:
SELECT field1, field2 from Table1 where field3=value1

Maybe after I get some Cider posted.

Here’s the “doughnut” class. I’m sure there’s a better name for this kind of control–I just don’t know it.

Doughnut = class(Control)

function Doughnut:init(s, left, bottom, right, top, 
    min, max, val, callback)
    Control.init(self, s, left, bottom, right, top, callback)
    self.controlName = "Doughnut"
    self.min = min
    self.max = max
    self.val = val
    self.fontSize = 14
    self.intervals = 15
    self.highlight = color(206, 223, 172, 255)
    self.coolColor = color(0, 255, 107, 255)
    self.warmColor = color(247, 244, 22, 255)
    self.hotColor = color(247, 25, 18, 255)
    self.warm = 9
    self.hot = 14
end

function Doughnut:draw()
    local i, x, w, h
    pushStyle()
    pushMatrix()
    smooth()
    noStroke()
    translate(self:midX(), self:midY())
    fontSize(self.fontSize)
    
    fill(self.background)
    ellipse(0, 0, self:width())
    fill(255, 255, 255, 67)
    ellipse(-5, 5, self:width()-10)
    fill(0, 0, 0, 67)
    ellipse(5, -5, self:width()-10)
    fill(self.background)
    ellipse(0, 0, self:width()-10)
    strokeWidth(2)
    stroke(self.foreground)
    fill(255, 255, 255, 74)
    ellipse(0, 0, self:width() / 2 + 10)
    noStroke()
    fill(self.foreground)
    w, h = textSize(self.val)
    text(self.val, 0, h/2)
    fill(self.highlight)
    
    text(self.text, 0, -h/2)
    rotate(180)
    x = (self:width() / (self.intervals / 3.14) ) / 2
    rotate(360 / self.intervals)
    noStroke()
    for i=1,self.intervals do
        rotate(-360 / self.intervals)
        fill(self.foreground)
        if self.val >= (self.max-self.min) / self.intervals
         * i + self.min then
            fill(self.coolColor)
            if i >= self.warm then
                fill(self.warmColor)
            end
            if i >= self.hot then
                fill(self.hotColor)
            end
        end
        
        ellipse(0, self:width() / 4 + self:width() / 8, x)
        
    end
    popMatrix()
    popStyle()
end

doughnut is in, but for some reason the TextBox from @twpster isn’t playing nicely; editing the CiderControl properties blanks out the name and label of the control when selected. Gists have been updated.

Hi all,
I really like Cider. I had the need of a pretty table display and I made the following modest addition to cider. It can be used as a slightly more general multibutton or just as a display. It goes without saying that you can do whatever you want with it :slight_smile:

-- the toucharray class takes a string in the latex format rows separated by & and ---
-- columns by \\\\ and produces a touchable array whose topleft corner is is at x,y and whose 
-- celsizes are either automatic or given by the user. 
-- the typical call is  a=touchArray("aaaaaaaa aaaa & b \\\\ c& d & t\\\\ a& 5&", 300,300, "single") or
--  a=touchArray("aaaaaaaa aaaa & b \\\\ c& d & t\\\\ a& 5&", 300,300, "single",50,50)
-- or a=touchArray("aaaaaaaa aaaa & b \\\\ c& d & t\\\\ a& 5&", 300,300)
-- the single variation allows one to choose a unique cell
--the table self.selected is a the set of selected cells, that is the 
-- value of self.selected[1..","..2] is true if the cell 1,2 is touched and false otherwise
--  you can check if the cell i,j is selected via self:check(i,j) and
-- you can get the text in the cel i,j by self.array[i][j].text

touchArray = class()

function touchArray:init(string, x,y,type, cellsizex, cellsizey)
    
      self:arrange(string)

      if cellsizex~=nil then self.celsizex=cellsizex textWrapWidth(cellsizex) 
      end 
      if cellsizey~=nil then self.celsizey=math.max(cellsizey,20*self.size/self.celsizex) 
        else   self.celsizey=math.max(self.celsizey,20*self.size/self.celsizex) 
      end
     self.selected={}
 
     self.x = x
     self.y= y
    self.type=type
    
     self.array={}
     for i,v in pairs(self.tab) do
        self.array[i]={}
        for j,k in pairs(v) do
            table.insert(self.array[i],cell(k,x+self.celsizex*(j-1),y-
            self.celsizey*i,x+self.celsizex*j,y-self.celsizey*(i-1)))
            self.selected[i..","..j]=false
        end
     end
end

function touchArray:arrange(str)
    self.tab={}
    self.celsizex=0
    self.celsizey=0
    i=1
    
    for a in string.gmatch(str,"([^\\\\]+)") do
      self.tab[i]={}
        for b in string.gmatch(a,"([^&]+)") do
     
          d=b:match "^%s*(.-)%s*$"   
          w, h = textSize(d)
          self.celsizex=math.max(self.celsizex, w)
          self.celsizey=math.max(self.celsizey,h)
          table.insert(self.tab[i], d)
        end
       i = i + 1
       end
    self.size=self.celsizex
end

function touchArray:draw()
    textWrapWidth(self.celsizex)
    for i , v in pairs(self.array) do 
        for j, k in pairs(v) do
        
            
          k:draw() 
            
        end
    end
end
function touchArray:check(i,j)
        return self.selected[i..","..j]
    end

function touchArray:touched(touch)
    for i , v in pairs(self.array) do 
        for j, k in pairs(v) do
            self.selected[i..","..j]=k.selected
            k:touched(touch)
            if self.type=="single" then
            if k.selected then
                for a,b in pairs(self.array) do 
        for c,d in pairs(b) do
            if d ~= k then d.selected=false 
            end end end end end 
        end
    end
        
    -- Codea does not automatically call this method
end
cell=class(Control)
function cell:init(string,x,y,z,w)
Control.init(self,string,x,y,z,w)
self.selected=false
end
function cell:draw()
    if self.selected then
        self.background =color(175, 22, 47, 255)
        else self.background=color(255, 255, 255, 255)
        
        end 
        Control.draw(self)
        
        end
function cell:touched(touch)
    if self:ptIn(touch.x, touch.y) then
        if touch.state == BEGAN  then
            self.selected = not self.selected
        end
        return true
    end
    return false
end

```

Interesting code - has potential to be a grid/table display of data. I’m not sure that I would only configure a LaTeX string though - I think I’m going to extend it to take Table as most Lua code seems to rely on Tables.