SkillAgentSearch skills...

Luce

Luce - a GUI module for Lua based on JUCE

Install / Use

/learn @peersuasive/Luce
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

==== Luce


A GUI Module for Lua (based on JUCE)

.. image:: http://peersuasive.github.io/images/lua-inside.png

Luce 0.3.4 sometimes, it won't fail released ! <https://github.com/peersuasive/luce/releases/tag/v0.3.4>__

Downloads_ for Linux, Windows, OS X, iOS and Android are available.

What is Luce ?

Luce is a Lua <http://lua.org>_ module for GUI programming based on the portable, embeddable, remarkable C++ library JUCE <http://www.juce.com>_.

It can be used as an ordinary module for pure lua 5.1/lua 5.2/luajit 2.X scripts or as a library for C++/Lua projects.

Although based on JUCE, Luce isn't aiming at becoming a binding for JUCE, though the low level API free of Luce features could be used as such.

Luce has Lua in mind and will be developped for lua developpers.

Lua essence is to be "a powerfull, fast, lightweight embeddable scripting language." And so would Luce be too.

Luce is light, fast and easily portable <https://github.com/peersuasive/luce_embeddable>_, thanks to Lua and JUCE itself.

As of now, it's supported on Linux, Windows and Mac OS X, with partial support for iOS and Android.

Getting started

  1. download_ the lua module for your environment

  2. put it somewhere in your lua modules path (ex: /usr/local/share/lua/5.1)

  • if you're on Linux, you can also use the provided luarock:

    Check the requirements_, then:

    for lua 5.1::

    ~$ luarocks install https://github.com/peersuasive/luce/raw/master/luce-scm-0.rockspec

    for lua 5.2::

    ~$ luarocks install https://github.com/peersuasive/luce/raw/master/luce-scm52-0.rockspec

    for lua 5.3::

    ~$ luarocks install https://github.com/peersuasive/luce/raw/master/luce-scm53-0.rockspec

  • if you don't know JUCE, you should consider having a look at its documentation <https://www.juce.com/api/annotated.html>__ as Luce low level API matches for the most part JUCE's own API.

    For more explanations, see Differences with JUCE_ and Luce design_

A first app: say hello

.. code:: lua

local title = "Hello World!"

local app, luce = require"luce.LApplication"(title, ...) -- create a basic Application
                                                         -- with command line parameters

local timer = luce:Timer() -- a timer for the animation

local function MainWindow(args)  -- our main component class
                                 -- will receive command line arguments or starting events

    local app, luce = app, luce    -- just to put these in the local environment
    local Colours   = luce.Colours -- id.
    local wsize     = {800,600}    -- the size of our window
    local isPaused  = false        -- holds the animation state

    local mc = luce:MainComponent("MainComponent") -- our main component
    local documentWindow = luce:Document(title)    -- create a document window to hold the main component

    local button = luce:TextButton("quit")  -- a button to close the app
    button.buttonText = "Quit"              -- visible text of the button
    button:setLookAndFeel(4)                -- change look-and-feel
    button.bounds     = { 10, 10, 100, 20 } -- and position it (x,y,w,h)

    ---
    -- set some action on button click
    ---
    button:buttonClicked(function()
        app:quit()
    end)

    ---
    -- say hello to the world with a simple animation
    ---

    -- just a dumb function to increase font size and pick a predefined colour
    local currentSize, baseSize, maxSize = 12.0, 12.0, 32.0
    local colours    = { Colours.black, Colours.red, Colours.yellow, Colours.green, Colours.blue }
    local currentCol = 1
    local function changeSize()
        currentSize = (currentSize<maxSize) and currentSize+0.5 or baseSize
        currentCol  = (currentCol>=#colours) and 1 or currentCol+1
        return currentSize, colours[currentCol]
    end

    -- draw the message
    mc:paint(function(g)
        -- draw a background
        g:fillCheckerBoard( luce:Rectangle(mc:getBounds()), 48, 48, Colours.lightgrey, Colours.white) 
        -- get new font size and colour
        local size, colour = changeSize()
        -- draw text
        g:setFont(size)
        g:setColour(luce:Colour(colour))
        g:drawText("Hello World!", mc:getLocalBounds(), luce.JustificationType.centred, true);
    end)

    -- animate it a bit via the timer callback
    timer:timerCallback(function()
        if(mc:isShowing() and not(isPaused))then
            mc:repaint()
        end
    end)
    timer:startTimer (1000/60)

    ---
    -- add some key shortcuts
    ---
    local K  = string.byte 
    local kc = setmetatable( 
        luce.KeyPress.KeyCodes, { __index = function()return 0 end } ) -- just a little trick to always get a valid keycode
                                                                       -- see https://www.juce.com/api/classKeyPress.html for
                                                                       -- available key-codes
    documentWindow:keyPressed(function(k)
        local k, m = k:getKeyCode(), k:getModifiers() -- get current key-code and modifiers status
        if (k==K"Q" or k==K"q") 
                and (m:isCommandDown() or not(app.os.osx)) then -- if Q is pressed or, on OS X, cmd+Q
            app:exit(0)     -- close the application with an normal exit state (0 by default)

        elseif (k==K"w" or k==K"W") and (m:isCommandDown() ) then -- if cmd/ctrl + W is pressed
            documentWindow:closeWindow() -- close the window
                                         -- on Linux and Windows, this has the effect of closing the application too,
                                         -- but on OS X, only the active window is closed by default
                                         -- however, if true is passed to closeWindow()
                                         -- and this is the last remaining Document
                                         -- the app will close the window and quit the application
        elseif (k==kc.spaceKey) then
            -- toggle rendering pause
            isPaused = not(isPaused)
        else
            return false -- don't consume key
                         -- returning false, nil or not returning anything
                         -- has the same effect
        end
        return true     -- tell the OS we have consumed this key
    end)

    ---
    -- add all components and display
    ---

    mc:setSize(wsize)
    mc:addAndMakeVisible(button)                -- add the component to our main component
    documentWindow:setContentOwned( mc, true )  -- add the main component to the document window

    ---
    documentWindow:closeButtonPressed(function() -- the user asked to close the current window...
        documentWindow:closeWindow()             -- so let's close it our way
                                                 -- if this action's not taken, it'll close the app by default
    end)
    documentWindow:setSize(wsize)   -- set dimensions for the window
                                    -- on iOS and Android, it'll just set a fullscreen
    documentWindow:setVisible(true) -- display the document
    return documentWindow           -- return it for the application to actually display it
end

local manual      = false       -- set true if you want to add your own process running along with the main loop
local osx_delayed = false       -- set true if you don't want your app to display a window immediatly on OS X
                                -- but wait for user input before, like providing a file,...
local poller      = function()  -- the callback you want to run in manual mode
    print "I'm in a loop!"
end
return app:start( MainWindow, manual and {poller,100}, osx_delayed ) -- returns the exit state

A more complete example using only the low level API

.. code:: lua

local luce = require"luce"()

---
--- create a default JUCEApplication
---
local mainWindow = luce:JUCEApplication("My App")

---
--- create a DocumentWindow with name "Document Window"
---
local dw = luce:DocumentWindow("Document Window")
-- rename it
dw.name = "Luce Example Application"

---
--- create a MainComponent, to be hosted by the Document Window
---
local mc = luce:MainComponent("The Main Component")

---
--- create a button named "TheButton" with text "a button"
---
local button = luce:TextButton("TheButton")
button:setButtonText( "a button" ) -- or button.buttonText = "a button", like button2 below

--- add a callback for when button is clicked
button:buttonClicked(function(...)
    print("button clicked !!")
end)

--- change component look and feel
local button2 = luce:TextButton("TheButton2")
button2.buttonText = "button with a different look and feel"

--- add a callback for when button is clicked
button2:buttonClicked(function(...)
    print("button 2 clicked !!")
end)

--- set a different look and feel for button2
button2:setLookAndFeel(3)

---
--- create a Label
---
local label = luce:Label("A Label")

--- Label's setText has an optional parameter to send a notification when its content's changed
--- by default, it sends nothing:
label.text = "a bit of content" -- default to dontSendNotification

--- set a callback for label text ch

Related Skills

View on GitHub
GitHub Stars129
CategoryDevelopment
Updated4mo ago
Forks14

Languages

C++

Security Score

77/100

Audited on Nov 13, 2025

No findings