Skip to content
stevedonovan edited this page Feb 21, 2013 · 3 revisions

wxLua is a comprehensive binding to the wxWidgets cross-platform GUI framework.

It is straightforward to write Moonscript programs that use this API (provided they are on the Lua module binary path). The result is definitely cleaner than the equivalent Lua, not to mention the original C++!

-- tree.wx.moon
require "wx"

-- create a table to store any extra information for each node like this
-- you don't have to store the id in the table, but it might be useful
-- treedata[id] = { id=wx.wxTreeCtrlId, data="whatever data we want" }

treedata = {}

treedata.put = (id,str) ->
    val = id\GetValue!
    treedata[val] = id:val, data:str

any = wx.wxID_ANY
defpos = wx.wxDefaultPosition
defsize = wx.wxDefaultSize

main = ->
    frame = wx.wxFrame wx.NULL, any, "wxLua wxTreeCtrl Sample",
                        defpos, wx.wxSize(600, 400),
                        wx.wxDEFAULT_FRAME_STYLE

    -- create the menubar and attach it
    fileMenu = wx.wxMenu!
    fileMenu\Append wx.wxID_EXIT, "E&xit", "Quit the program"
    helpMenu = wx.wxMenu!
    helpMenu\Append wx.wxID_ABOUT, "&About", "About the wxLua wxTreeCtrl Sample"

    menuBar = wx.wxMenuBar!
    menuBar\Append fileMenu, "&File"
    menuBar\Append helpMenu, "&Help"
    frame\SetMenuBar menuBar

    frame\Connect wx.wxID_EXIT, wx.wxEVT_COMMAND_MENU_SELECTED,->
        frame\Close true

    frame\Connect wx.wxID_ABOUT, wx.wxEVT_COMMAND_MENU_SELECTED,->
        wx.wxMessageBox 'This is the "About" dialog of the wxLua wxTreeCtrl sample.\n'..wxlua.wxLUA_VERSION_STRING.." built with "..wx.wxVERSION_STRING,
                        "About wxLua",
                        wx.wxOK + wx.wxICON_INFORMATION,
                        frame

    splitter = wx.wxSplitterWindow frame,any,defpos,defsize

    -- create our treectrl
    tree = wx.wxTreeCtrl splitter, any, defpos, defsize,
                        wx.wxTR_LINES_AT_ROOT + wx.wxTR_HAS_BUTTONS


    -- create our log window

    textCtrl = wx.wxTextCtrl splitter, any, "", defpos, defsize,
                        wx.wxTE_READONLY + wx.wxTE_MULTILINE

    splitter\SetMinimumPaneSize 50
    splitter\SplitVertically tree, textCtrl, 200


    root_id = tree\AddRoot "Root"
    treedata.put root_id, "I'm the root item"

    for idx = 0, 10
        parent_id = tree\AppendItem root_id, "Parent (#{idx})"
        treedata.put parent_id, "I'm the data for Parent (#{idx})"
        for jdx = 0, 5
            child_id = tree\AppendItem parent_id, "Child (#{idx},#{jdx})"
            treedata.put child_id, "I'm the child data for Parent (#{idx},#{jdx}))"
        if idx == 2 or idx == 5
            tree\Expand parent_id

    tree_event = (evnt,name) ->
        tree\Connect evnt,(event) ->
            value = event\GetItem!\GetValue!
            textCtrl\AppendText "Item #{name}: #{tostring(value)} '#{treedata[value].data}'\n"

    -- connect to some events from the wxTreeCtrl
    tree_event wx.wxEVT_COMMAND_TREE_ITEM_EXPANDING,"expanding"

    tree_event wx.wxEVT_COMMAND_TREE_ITEM_COLLAPSING, "collapsing"

    tree_event wx.wxEVT_COMMAND_TREE_ITEM_ACTIVATED, "activated"

    tree_event wx.wxEVT_COMMAND_TREE_SEL_CHANGED, "sel changed"

    tree\Expand root_id

    frame\Show true

main!

wx.wxGetApp!\MainLoop!

It's convenient to move some common boilerplate into a helper module. Here is the wxGrid example, using wxm:

wxm = require 'wxm'
   
frame = wxm.frame "wxLua wxGrid Sample",{},{350,250}

ids = EXIT: wxm.ID_EXIT, ABOUT:wxm.ID_ABOUT

import menu from wxm
menu.bar {
    menu "&File", {
        menu.item -1, "&Open", ->
            print 'opening sesame'
        menu.item ids.EXIT, "E&xit\tCtrl-X", "Quit the program",->
            frame\Close!
    }
    menu "&Help", {
        menu.item ids.ABOUT, "&About\tCtrl-A", "About the Grid wxLua Application",->
            wxm.MessageBox "Simplified wx with Moon",  "About wxLua",
                  wxm.OK + wxm.ICON_INFORMATION,
                  frame            
    }
}

wxm.toolbar nil, { 
    {ids.EXIT, 'Exit', 'ERROR'}
    {-1,'-'}
    {ids.ABOUT, 'About', 'HELP'}
}

frame\CreateStatusBar 1
frame\SetStatusText "Welcome to wxLua."

grid = wxm.Grid frame, wxm.ID_ANY

grid\CreateGrid 10, 8
grid\SetColSize 3, 200
grid\SetRowSize 4, 45
grid\SetCellValue 0, 0, "First cell"
grid\SetCellValue 1, 1, "Another cell"
grid\SetCellValue 2, 2, "Yet another cell"
grid\SetCellFont 0, 0, wxm.Font 10, wxm.ROMAN, wxm.ITALIC, wxm.NORMAL
grid\SetCellTextColour 1, 1, wxm.RED
grid\SetCellBackgroundColour 2, 2, wxm.CYAN

wxm.go!

One of the first things that wxm does is make a copy of wx, getting rid of the terrible redundancy of having all entries prefixed with 'wx'. Then basic frame and menu support is provided. The essential idea is this: GUI programming is not so very hard, and an API does not have to reflect its original implementation language (in this case, a fairly old-fashioned dialect of C++).

-- wxm.moon
-- 
wx = require "wx"

wxm = {k\sub(3),v for k,v in pairs wx}

_frame = nil

wxm.frame = (caption,pos,size) ->
    if not next(pos) then pos = wxm.DefaultPosition
    if not next(size)
        size = wxm.DefaultSize
    elseif type(size)=='table'
        size = wxm.Size unpack size
    _frame = wxm.Frame wx.NULL, wxm.ID_ANY, caption, pos, size 
    _frame
    
wxm.bitmap = (name,kind) ->
    kind = kind or 'MENU'
    wxm.ArtProvider.GetBitmap wx['wxART_'..name], wx['wxART_'..kind]
    
wxm.menu = {}

wxm.menu.dropdown = (text,items) ->
    menu = wxm.Menu "", wxm.MENU_TEAROFF
    for item in *items
        menu\Append unpack item
    {menu, text}
        
setmetatable wxm.menu, __call:(self,...) -> self.dropdown ...

id_counter = nil

wxm.nextID = ->
    if not id_counter then id_counter = wxm.ID_HIGHEST
    id_counter += 1
    return id_counter
    
wxm.menu.item = (id,text,hintstr,callback) ->
    if type(hintstr) == 'function' then callback = hintstr
    if not hinstr then hintstr = ''
    if id == -1 then id = wxm.nextID!
    if callback
        _frame\Connect id, wxm.EVT_COMMAND_MENU_SELECTED, callback
    {id,text,hintstr}

wxm.menu.bar = (items) ->
    mbar = wxm.MenuBar!
    for item in *items
        mbar\Append item[1], item[2]
    _frame\SetMenuBar mbar

wxm.toolbar = (style,items) ->
    style = style or wxm.NO_BORDER + wxm.TB_FLAT + wxm.TB_DOCKABLE
    tbar = _frame\CreateToolBar style
    for item in *items
        id, text, bm, hintstr = item[1], item[2], item[3], item[4]
        if type(bm) == 'string' then bm = wxm.bitmap bm
        if id == -1 and text == '-' 
            tbar\AddSeparator!
        else
            tbar\AddTool id, text, bm, hintstr or text
    tbar\Realize!
    
wxm.go = ->
    _frame\Show true
    wxm.GetApp!\MainLoop!
    
return wxm
Clone this wiki locally