Soda v0.7: gorgeous and powerful GUI/ windowing/ button library. Now with fully selectable text.

13

Comments

  • @juce, привет, давай дружить

  • Why THANKS?
    

    @Ignatz, what do you think about Thx, he didn't do anything

  • IgnatzIgnatz Mod
    Posts: 5,396

    He is trying to help you explain your problem

  • This is really super super super super sweeeeet.

  • AnatolyAnatoly Mod
    Posts: 891

  • Posts: 2,020

    @TokOut thanks for making the video!

  • AnatolyAnatoly Mod
    Posts: 891

    No problem :)

  • AnatolyAnatoly Mod
    Posts: 891

    @yojimbo2000, suggestions for 8.0:TextParagraph, TextBox by clicking return, an alert. Alert with buttons instead right, left, they will be from bottom to up, and more buttons. A demo window, with the Flappy Bird Game in examples. Also a simple Window as Web Brouser. With a textbox of the link. Also may a page with an textparagraph in lua colored formatting (function is purple, parameter is light blue, self is purple and the words after self blue.).

  • AnatolyAnatoly Mod
    Posts: 891

    And plz fix this bug: @yojimbo2000, select all text (in the text library) Press any key, the text will change to key .. text instead to key, it works only with backspace!

  • AnatolyAnatoly Mod
    edited September 2016 Posts: 891

    Soda Installer

    local url = "https://raw.githubusercontent.com/Utsira/Soda/master/tabs/"
    
    local function install(data)
        --parse plist into list of tab files
        local array = data:match("<key>Buffer Order</key>%s-<array>(.-)</array>")
        local files = {}   
        for tabName in array:gmatch("<string>(.-)</string>%s") do
            table.insert(files, {name = tabName})
        end   
        --success function
        local function success(i, name, data)
            if not data then alert("No data", name) return end
            print("Loaded "..i.."/"..#files..":"..name)
            files[i].data = data
            for i,v in ipairs(files) do
                if not v.data then 
                    return --quit this function if any files have missing data
                end
            end
            --if all data is present then save...
            for i,v in ipairs(files) do
                saveProjectTab(v.name, v.data)
                print("Saved "..i.."/"..#files..":"..v.name)
                load(v.data)() --load...
            end
            setup() --...and run
        end
        --request all the tab files
        for i,v in ipairs(files) do 
            local function retry(error) --try each file twice, in case of time-outs
                print(error, v.name.." not found, retrying")
                http.request(url..v.name..".lua", function(data) success(i, v.name, data) end, function(error2) alert(error2, v.name.." not found") end)
            end
            http.request(url..v.name..".lua", function(data) success(i, v.name, data) end, retry)
        end
    end
    http.request(url.."Info.plist", install, function (error) alert(error) end)
    
  • AnatolyAnatoly Mod
    Posts: 891

    @yojimbo2000: Suggestion to Soda;

    1) By the Scroll Text where Latin text create A scroll to see where you are currently
    2) A text paragraph where you can edit different formatting (gpfonts, bold, ...)
    3) [demo] Your X-wing from the Star Wars competition as game in a window.
    4) [demo] If it's possible, a web Brouser window, where you can specify things.
    5) [fix please] Fix glitches by scrolling to fast please
    6) Create a new subject (like ABOUT, SCROLL, ...) for ACOUNT, where you can create acounts or delete them to have ACESS to these things above^^
    
  • @yojimbo2000 how should i stop the touch being propagated to elements underneath the soda.window?

  • edited January 2016 Posts: 2,020

    Soda touch events return true if the touch registers. So in your touched function you can put something like

    if Soda.touched(touch) then return end --exit if Soda touch detected
    -- your touch code goes here
    

    I should update the Main template to reflect this. Thanks for raising this.

    EDIT: whoops, turns out I forgot to push this change to the repo. If you reinstall with the repo, Soda touched should now behave as described above.

    Let me know if this creates any problems.

  • Thanks, that did the trick!

  • @yojimbo2000: Don't want to make noise here but have to leave a big thank you for your contribution and what I'm learning from your code!

  • Posts: 2,020

    No problem, looking forward to seeing what you create with it!

  • AnatolyAnatoly Mod
    Posts: 891

    How to make round buttons?

  • Posts: 567

    Is there a convenient way to change a dropdown list after it has been first defined in the setup?

  • Posts: 2,020

    What sort of changes are you wanting to make?

  • Posts: 567

    Just change the text items in the pulldown list

  • Posts: 2,020

    If it's changing individual items in the list when they are tapped on, that should be easy, but to change an entire list it might be easier to kill the old list and create a new one.

    I'm waiting for a new lightning cable to arrive before I can charge my iPad, so I won't be able to test anything right now.

  • Posts: 2,020

    An example of manipulating the selected item when it's tapped on. The callback to a list item returns 3 variables, the list itself, the item selected, and the selected item's title.

    untested, but should work:

    local function list_callback(this_list, item, item_title)
        --some logic here to decide what you want to do to the selected item
       item.title = "You selected this item"
    end
    
    Soda.DropdownList{
      --list parameters
      callback = list_callback
    }
    
  • Just a heads-up on what seems to be a bug in the demo: on the "Dialogs" tab, there are two buttons at the bottom that are labeled "Window" and "blurred window". Both buttons bring up a window that looks like it should be dismissible three ways: tapping the X in the corner, tapping the Cancel button, or tapping the OK button.

    The X and the Cancel button do dismiss the window, the OK button does not: pressing the OK button does nothing. Totally not a huge thing at all, just thought you might want to know.

  • Posts: 2,020

    Hi @UberGoober , i posted a reply to this in the other thread, https://codea.io/talk/discussion/comment/69600/#Comment_69600

  • Posts: 2,020

    Maybe it is better to have the discussion in this thread. Re the close button issue, hard for me to debug that as I don't see that behaviour. You might have made some changes? The easiest thing might be a fresh install of Soda (using the installer). Have a look at the top of the Window tab, the logic for triggering the close action should look like this:

    function Soda.Window:init(t)
        t.shape = t.shape or Soda.RoundedRectangle
        t.shapeArgs = t.shapeArgs or {}
        t.shapeArgs.radius = 25
        t.label = t.label or {x=0.5, y=-15}
        t.content = t.content or ""
        local callback = t.callback or null
        Soda.Frame.init(self, t)
    
        if t.ok then
            local title = "OK"
            if type(t.ok)=="string" then title = t.ok end
            Soda.Button{parent = self, title = title, x = -10, y = 10, w = 0.3, h = 40, callback = function() self:closeAction() callback() end} --style = Soda.style.transparent,blurred = t.blurred,
        end
    
        if t.cancel then
            local title = "Cancel"
            if type(t.cancel)=="string" then title = t.cancel end
            Soda.Button{parent = self, title = title, x = 10, y = 10, w = 0.3, h = 40, callback = function() self:closeAction() end,  subStyle = {"warning"}} --style = Soda.style.warning 
        end
    
        local closeStyle = {"icon", "button"}
        if t.blurred then
            closeStyle = {"icon"}
        end
        if t.close then
            Soda.CloseButton{
                parent = self, 
                x = 5, y = -5, 
                shape = Soda.ellipse,
                callback = function() self:closeAction() end, 
                subStyle = closeStyle --style = Soda.style.icon
            }
        end
       -- t.shadow = true
    
    end
    
    function Soda.Window:closeAction()     --do we want to hide this Window or kill it?
        if self.doNotKill then
            self:hide()
        else
            self.kill = true 
        end
    end
    
  • Posts: 2,020

    @UberGoober if you look at the video above, the windows are behaving correctly. @TokOut have you ever considered a career as a tester?

  • I swear I installed it with the installer given on the git readme, and never touched the default installation at all. I haven't tried reinstalling though, so I should do that.

  • Have done fresh reinstall, same results. Here is video:

  • I can't figure out how to download?

  • Posts: 2,020

    Copy and paste installer into a Codea project and run.

    https://codea.io/talk/discussion/comment/66696/#Comment_66696

  • Alright I got it now. Thanks btw! But what is it for? What does it do?

  • AnatolyAnatoly Mod
    Posts: 891

    https://github.com/TokOut/InOneClass/blob/master/Brouser.lua

    Guys, I was working on this web Brouser with lua's http.request, but for my non good development skills, it is buggy and laggy, and... Long code...

    Maybe @yojimbo2000 will look at it, and improve a better version in his Soda.

    --[[ Are you going to make it? @yojimbo2000? Soda would be the famoust creation on Codea :) ]]

    I just mean, continue my failures project

  • AnatolyAnatoly Mod
    Posts: 891

    Also, @yojimbo2000, please put a link in your first post on this topic (OP). Which redirects to here:

    https://codea.io/talk/discussion/comment/66696/#Comment_66696

  • AnatolyAnatoly Mod
    Posts: 891

    Bug Reportation

    Imgur

    Start in landscape orientation and rotate to any portrait orientation.

    • Text is not translated to a new line, which appears after WIDTH
  • Posts: 2,020

    @UberGoober

    In the Window tab, line 22, change the line if callback() then self:closeAction() end to callback() self:closeAction()

    Pull requests are welcome. Fork the repo, and if you spot a bug, fix it on your branch, submit a pull request, and I can merge it back in. I appreciate that using git with Codea isn't the easiest thing, or might feel too much like work :-)

  • Posts: 2,020

    @TokOut I don't think you could make a very good web browser with Lua, because it doesn't have the necessary language features. E.g. As I think you discovered on another thread, Lua's string manipulation features (a kind of paired down form of regex ) are not powerful enough to parse HTML properly (let alone interpret JavaScript). & Codea's OpenURL does a good enough job if you just need to display stuff. Did you know that it even works with HTML files that you can bundle with your project?

  • Posts: 2,020

    But what is it for? What does it do?

    @EvanDavis that is for you to discover

  • @yojimbo2000 nice job remote debugging! That worked.

    Not sure if bug or feature, btw: repeatedly pushing the Window and Blur Window buttons causes more to appear on top of each other. With the blur window this is neat because the blur gets more extreme as the windows stack up.
  • edited October 2016 Posts: 2

    How can I block a password in a Soda TextEntry? I'd like either not to echo the input or to replace it with asterisks, for instance.

  • edited October 2016 Posts: 2,020

    @davidwk interesting question. As a quick fix, what you could do, in the text entry tab, change line 123 to

    self.text = string.rep("*", #self.input - self.start + 1) 
    

    But that would effect every text entry field, probably not what you want.

    The best approach would be to have a "filter" closure, that you pass into text entry, which can manipulate the text field. The default behaviour would be to pass the string straight through unmodified. Then you could easily define which text entry fields you want to obscure.

    It'd be set up in text entry init something like this:

    self.filter = t.filter or function(input) return input end
    

    Then, whenever self.text is set, you'd run it through the filter

    self.text = self.filter(self.text)
    

    To pass in the asterisking filter you'd define your text entry and then add the filter:

    passwordField.filter = function(input) return string.rep("*", #input) end
    

    I'm super busy with work right now, but if someone were to implement this and submit a pull request, I'd merge it into the repo.

  • @yojimbo2000 thanks, the filter logic works fine for asterisks. Not surprisingly, it doesn't work for Unicode filled circles (\u{25cf}).

  • Posts: 2,020
    Yeah, text entry used to work with Unicode in Soda, then at some point it broke. Need to look into that.
  • @yojimbo2000 , this came up in my conversion-to-Soda thread, but it seems to be a general Soda bug, so I'm posting this here.

    It's rather serious: Soda does not seem to support decimals as position coordinates.

    For example, this will not appear on screen for me:

        local inset = 40.035
        Soda.Button{
             title = "insetTest",
             x = inset, y = inset, w = 400, h = 200
        }
    

    But this will:

        local inset = 40
        Soda.Button{
             title = "insetTest",
             x = inset, y = inset, w = 400, h = 200
        }
    
  • Posts: 13

    Hi @yojimbo2000, sorry to bother, but I am struggling with this problem for some weeks, I can't go further without solving it. Any help is welcome.

    First I create buttons in screen:

    Botoes = class()
    
    function Botoes:init(x)
    
       Soda.Button{
    
        title = "Control", 
        subStyle = {"translucent"}, 
        x = -0.2, y = 0.18, w = 0.15, h = 0.07, 
        callback = 
            function()
            if painel.hidden==true then
            painel.hidden=false
        else
            painel.hidden=true
            end
        end
    
        }
    
    
    
         Soda.Button{
    
        title = "Cam", 
        subStyle = {"translucent"},
        x = -0.2, y = 0.11, w = 0.15, h = 0.07, 
        callback = 
            function()
            if camlen==2 then 
                camlen =1
             else
                camlen=2  
            end
    
        end
    
        }
    
        Soda.Button{
    
        title = "Help", 
        subStyle = {"translucent"},
        x = -0.2, y = 0.04, w = 0.15, h = 0.07, 
        callback = 
            function()
                Soda.TextWindow{ 
                    title = "About", 
                                textBody =[[
           About ]] ,
                        ok = "Visit site",
    
                        alert = true, close = true,
                    y=0.6, h = 0.7, w = 0.8,
                callback = function()
                    openURL("https://vascular.pro")
            end
    
                }
            end
    }
    
    end
    
    function Botoes:draw()
    
    end
    
    function Botoes:touched(touch)
    
    end
    

    Then I create panel:

    Controles = class()
    painel={}
    
    function Controles:init(x)
    
    
    
         painel = Soda.Window{
           title = "Controls", 
           hidden = true,
    
    
       }
    
        AlgoSwitch = Soda.Switch{
            parent=painel,
    
            y = 0.7,
            title = "Algorithm",
            on = true
    
    
        }
    
         filtro = Soda.Slider{
            parent=painel,
            title = "Blue / Green",
    
      y=0.5,
            min = 0, max = 1, start = 0.8,
            decimalPlaces = 2
    
    
        }
        bright=Soda.Slider{
            parent=painel,
            title = "Brightness",
            y=0.2,
            min = 0, max = 10, start = 3.5,
            decimalPlaces = 1
    
        }
    
    end
    
    function Controles:draw()
    
    end
    
    function Controles:touched(touch)
    
    end
    

    But all the sliders and switch button inside the painel cannot be changed. They are kind of locked.
    What am I doing wrong?
    Thanks again for your help

  • edited November 2016 Posts: 2,020

    @UberGoober

    It's rather serious: Soda does not seem to support decimals as position coordinates.

    This is not a bug. It is a feature! ;)

    I realised that I didn't document the Soda coordinate system anywhere (maybe in a comment somewhere?).

    It goes like this. If the coordinate is a whole number greater than 1 it is treated as a regular coordinate, but relative to the parent frame.

    If the coordinate is negative, it expresses distance from the top/ right edge of the parent frame.

    And if the coordinate is a decimal, it represents position as a proportion of the parent's frame. So if you want to centre something in the middle of its parent, set x and y to 0.5. If you want it to be 90% of its parent's widht and height, set w and h to 0.9.

    I figured this "overloading" of the x/y coord would be OK, as generally you'd only want to express the coordinates of ui elements in whole numbers (tho in fact, retina iPad pixels are half numbers, 0, 0.5, 1, 1.5 etc).

    So x coord of 40.3 won't show, as its 40.3 times its parent width.

    In your example, don't set the position to HEIGHT * 0.3 or whatever, set it to 0.3 and let Soda calculate the coord based on whatever the containing frame's height is.

  • Huh. Ok. Overall that's a good way to do it, I think. I think you did explain it in the readme but you explained it more clearly here.

    The confusion in the readme is that, IIRC, in the readme you said that values between 0 and 1 would be used as proportions, not that any decimals would be used as proportions. It seems a bit nonsensical to treat values over 1 as proportions since they will always be positioned outside the bounds of their parent. No?

  • Posts: 2,020

    Yeah I was thinking of cases where you might want an object to overspill the bounds of its containing frame. But maybe you're right, having it that objects must be contained within their frames might be a useful restriction to have. Look at the parseCoord method in the Soda tab for the logic. Why not make some changes, then submit a pull request?

  • @yojimbo2000 , I see what you mean, and to be fair, I'm wrong to call it "nonsensical", since that's how UIView works on iOS too. View elements can appear anywhere outside the view's bounds unless you turn on the flag clipsToBounds.

    I guess it's good to keep consistency in that regard--the only thing I'd recommend changing is to clarify in the documentation that the proportions count for all decimals, not just those between 0 and 1.

    Also I recommend clarifying that TextWindow and TextScroll don't support custom fonts or fontSizes or colors. I spent a long time banging my head against that.

  • Posts: 2,020

    @UberGoober you can have custom fonts and styles in text boxes, but it has to be a monospaced font (Soda uses Inconsolata by default), because calculating things like line wrapping and text selection is far too complex with a variable width font. The easiest way to do this might be to override Soda.style.default.textEntry or Soda.style.default.textBox (the defaults are defined in the Style tab. Properties are font fill and fontSize).

    Or create your own style. eg Soda.style.GooberStyle and then create a textBox table in there. When you initiate the text window, set style = Soda.style.GooberStyle as one of the parameters.

    I realise I never got round to documenting the style functionality. Still, you have the source code, shouldn't be that hard to work out. :-P

    I guess it's good to keep consistency in that regard--the only thing I'd recommend changing is to clarify in the documentation that the proportions count for all decimals, not just those between 0 and 1.

    Could you make these changes in GitHub (to readme.md) and then submit a pull request?

  • I'll see if I can figure out the github thing.

    Is there an equivalent of UILabel in Soda, an element whose sole job is displaying text? Or is the idea that a Button with no associated action should be used as a label?
Sign In or Register to comment.