Hello Guest it is March 28, 2024, 02:47:20 PM

Author Topic: wxLua and wxWidgets questions  (Read 2975 times)

0 Members and 1 Guest are viewing this topic.

Offline DBK

*
  •  9 9
    • View Profile
wxLua and wxWidgets questions
« on: November 29, 2017, 06:11:03 PM »
Hello everyone,

I'm developing a Mach4 Wizzard and am having a problem with grid blocks, specifically wxGridCellCoordsArray's returned by wxWidgets.  I believe it is a result of a bug in a wxLua wrapper for wxWidgets.

A couple questions:
  • The mailing list activity on wxLua's site has slowed to a crawl.  Is wxLua still in development?
  • This one is a longshot... Has anybody tried processing multiple block-selections on a grid?  See the attachment for an example. Sample code is attached as well - to show syntax highlighting.
  • Finally, does anybody know how to recompile wxLua with wxWidgets 3.01? Or at least how easy or hard it might be?  Mach4 obviously has it done.  I am developing on another machine without Mach4 installed and am using the Windows install of wxLua to develop with. The latest version from their web-page is compiled with 2.8.12.
Text version here:
Code: [Select]
    local wxGridCellCoordsArray BTL = (grid:GetSelectionBlockTopLeft())   
    local wxGridCellCoordsArray BBR = (grid:GetSelectionBlockBottomRight())   
   
    print("BTL=",BTL)
    print("BTL Count="..BTL:GetCount(), "BBR Count="..BBR:GetCount()) --These print to an output window in wxLuaEdtor
 grid.SetCellValue(grid,2,0,"Ct="..BTL:GetCount()) --print doesn't show in mcLua, so I put it on the grid.
            --correctly displays the number of blocks selected in the grid

    local wxGridCellCoords topleft = (BTL:Item(1)) --this line blows up mcLua and wxLuaEditor
    row = topleft:GetRow()
    col = topleft:GetCol()
    print("topleft=", topleft)
    print("Row="..row,"Col="..col)

The two calls to GetSelectionBlock... work fine as a subsequent call to GetCount on each returns the correct value.
The call to Item(1) should return the first block’s row/col pair, but no matter how I try I can’t get it to return good values. I had some erroneous values at one time, but it wasn’t crashing the editor.
I have no expectation that anybody must troubleshoot this, but if some curious soul would like a try at it, I have included the code.  Just put it in a menu or button event, of course.

Thanks,    David

Offline DBK

*
  •  9 9
    • View Profile
Re: wxLua and wxWidgets questions
« Reply #1 on: December 01, 2017, 04:14:18 AM »
I wasn't thinking in my last post.  I have included the test program to make it easier to test than just supplying the snippet above.

It's just the grid example that comes with wxLua 2.8.12.  The snippet is inserted into the Help About menu event at line 40.  I just use the mouse and drag select a block in the grid and then select the menu item.  You can select more than one if you hold the ctrl key down until you are done selecting.  You can run it in the wxLuaEditor or mcLua (Pure vanilla Lua. No Mach4 calls in it, so it will not move your machine).

Code: [Select]
-----------------------------------------------------------------------------
-- Name:        grid.wx.lua
-- Purpose:     wxGrid wxLua sample
-- Author:      J Winwood
-- Created:     January 2002
-- Copyright:   (c) 2002 Lomtick Software. All rights reserved.
-- Licence:     wxWidgets licence
-----------------------------------------------------------------------------

-- Load the wxLua module, does nothing if running from wxLua, wxLuaFreeze, or wxLuaEdit
package.cpath = package.cpath..";./?.dll;./?.so;../lib/?.so;../lib/vc_dll/?.dll;../lib/bcc_dll/?.dll;../lib/mingw_dll/?.dll;"
require("wx")

local frame = wx.wxFrame(wx.NULL, wx.wxID_ANY, "wxLua wxGrid Sample",
                         wx.wxPoint(25, 25), wx.wxSize(350, 250))

local fileMenu = wx.wxMenu("", wx.wxMENU_TEAROFF)
fileMenu:Append(wx.wxID_EXIT, "E&xit\tCtrl-X", "Quit the program")

local helpMenu = wx.wxMenu("", wx.wxMENU_TEAROFF)
helpMenu:Append(wx.wxID_ABOUT, "&About\tCtrl-A", "About the Grid wxLua Application")

local menuBar = wx.wxMenuBar()
menuBar:Append(fileMenu, "&File")
menuBar:Append(helpMenu, "&Help")

frame:SetMenuBar(menuBar)

frame:CreateStatusBar(1)
frame:SetStatusText("Welcome to wxLua.")

frame:Connect(wx.wxID_EXIT, wx.wxEVT_COMMAND_MENU_SELECTED,
    function (event)
        frame:Close()
    end )




frame:Connect(wx.wxID_ABOUT, wx.wxEVT_COMMAND_MENU_SELECTED,
    function (event)
    local wxGridCellCoordsArray BTL = (grid:GetSelectionBlockTopLeft())   
    local wxGridCellCoordsArray BBR = (grid:GetSelectionBlockBottomRight())   
   
    print("BTL=",BTL)
    print("BTL Count="..BTL:GetCount(), "BBR Count="..BBR:GetCount())
            --correctly displays the number of blocks selected in the grid

--    local wxGridCellCoords topleft = (BTL:Item(1)) --this line blows up wxLuaEditor
--    row = topleft:GetRow()
--    col = topleft:GetCol()
    print("topleft=", topleft)
    print("Row="..row,"Col="..col)
   
    end )






grid = wx.wxGrid(frame, wx.wxID_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, wx.wxFont(10, wx.wxROMAN, wx.wxITALIC, wx.wxNORMAL))
grid:SetCellTextColour(1, 1, wx.wxRED)
grid:SetCellBackgroundColour(2, 2, wx.wxCYAN)

frame:Show(true)

-- Call wx.wxGetApp():MainLoop() last to start the wxWidgets event loop,
-- otherwise the wxLua program will exit immediately.
-- Does nothing if running from wxLua, wxLuaFreeze, or wxLuaEdit since the
-- MainLoop is already running or will be started by the C++ program.
wx.wxGetApp():MainLoop()

Offline gorf23

*
  •  183 183
    • View Profile
Re: wxLua and wxWidgets questions
« Reply #2 on: December 01, 2017, 01:55:46 PM »
Code: [Select]
    local wxGridCellCoordsArray BTL = (grid:GetSelectionRows())   
    local wxGridCellCoordsArray BBR = (grid:GetSelectionCol())

This change seems not to crash not really sure what you are looking for...

Offline DBK

*
  •  9 9
    • View Profile
Re: wxLua and wxWidgets questions
« Reply #3 on: December 01, 2017, 03:30:49 PM »
Hello gorf23,

Thanks for your interest and desire to help!

There are several ways for a user to select multiple cells on a grid:
Click on the upper left corner -  Selects the entire grid.
Click on a row or col header-  Selects the entire row or column.
Click on a cell-  Select a single cell.
Click on a cell, and then drag the mouse to another cell -  Selects a block of cells.
Any combination of the the above (minus the first one) by holding a ctrl-key down during the selection process.

I hadn’t explained the goal of this routine before.  It’s to let the user select any number of cells that they wish to set to the same value. So, after selecting multiple cells and typing a value, “1.5” for instance, will populate every selected cell with “1.5”. The grid’s default action, is to only populate the cell with the border.  In, my picture of the block-selection above, it would be the cell with the value of “28.49”.  A grid in my program may have text cells and it wouldn’t make sense to process entire rows or columns, but just block-selection and individual cells the user picked.   
 
You didn’t show the entire snippet of your test, so I must assume that what you showed is all you changed. GetSelectedRows() and GetSelectedCols() wouldn’t help achieve my goal as stated above. But, I should point out, both of those routines return a wxArrayInt as specified in the (very difficult to interpret) wxLua Refrence Manual. And while it may not crash, it will produce erroneous results.

If we change the line you posted to:
Code: [Select]
local wxArrayInt BTL = (grid:GetSelectionRows())
Then it would return valid results (assumption: not tested), but not ones that I can use for the reasons stated in my goals above.

A little more detail is needed.
The two functions starting with “GetSelectionBlock” return an array of array’s.  An array of TopLefts-of-blocks that contain a two-item-array containing a row, col pair that defines that block top-left.

grid:Item() returns a wxGridCellCoords (the two element array containing the row,col pair). I should also point out that the arrays returned are not Lua arrays, hence having to get the underlying data out with another function call.

I have been able to show that they, at least, return the right number of blocks selected. But either, the row, col pair is corrupted, causing the grid:Item() call to crash, or the grid:Item() routine has a bug that causes it to crash.  I can’t tell which is happening.

The other possible reason for the crashing is that I have incorrectly interpreted the documentation and my syntax for the calls is actually at fault.   

Offline gorf23

*
  •  183 183
    • View Profile
Re: wxLua and wxWidgets questions
« Reply #4 on: December 01, 2017, 07:16:05 PM »
here is a little code I did its just shows reading a cell value and writing to a cell
and a event function() if the left button is pressed in a cell and changing row and col labels

not what your are looking for but maybe something useful here


Code: [Select]
[----------------------------------------------------------------------------


-- Load the wxLua module, does nothing if running from wxLua, wxLuaFreeze, or wxLuaEdit
--package.cpath = package.cpath..";./?.dll;./?.so;../lib/?.so;../lib/vc_dll/?.dll;../lib/bcc_dll/?.dll;../lib/mingw_dll/?.dll;"
--require("wx")

function CreateLables(Cnt)
RowGridLables =  {}
     RowGridLables[0] = "Name"
     RowGridLables[1] = "Date"
     RowGridLables[2] = "Year"
     RowGridLables[3] = "Time"
     RowGridLables[4] = "Phone"

ColsGridLables =  {}
     ColsGridLables[0] = "Col1"
     ColsGridLables[1] = "Col2"
     ColsGridLables[2] = "Col3"
     ColsGridLables[3] = "Col4"
     ColsGridLables[4] = "Col5"

--local Cnt = 5
local Rows = 0
local Colm = 0
    while   (Rows ~= Cnt)  and  (Colm ~= Cnt)   do
    wx.wxMessageBox("Rows = "..Rows.."  Gridnames = "..RowGridLables[Rows])
    UI.m_grid2:SetRowLabelValue( Rows, RowGridLables[Rows])
    UI.m_grid2:SetColLabelValue(Colm, ColsGridLables[Rows])
    Rows = Rows + 1
    Colm = Colm + 1
  end
     UI.m_grid2:SetCellValue( 0, 3, "This only" )
     UI.m_grid2:SetColFormatFloat(0, 4, 2);
     UI.m_grid2:SetCellValue( 0, 4, "3.1415" )
     UI.m_grid2:SetCellValue( 1, 2, "This only" )
     UI.m_grid2:SetColFormatFloat(0, 3, 2);
     UI.m_grid2:SetCellValue( 2, 3, "3.1415" )
    local value = UI.m_grid2:GetCellValue(2,3)
    wx.wxMessageBox("Row 2 Col 3 = "..value)
end


UI = {}



-- create MyDialog1
UI.MyDialog1 = wx.wxDialog (wx.NULL, wx.wxID_ANY, "", wx.wxDefaultPosition, wx.wxSize( 745,451 ), wx.wxDEFAULT_DIALOG_STYLE )
UI.MyDialog1:SetSizeHints( wx.wxDefaultSize, wx.wxDefaultSize )

UI.fgSizer3 = wx.wxFlexGridSizer( 0, 2, 0, 0 )
UI.fgSizer3:SetFlexibleDirection( wx.wxBOTH )
UI.fgSizer3:SetNonFlexibleGrowMode( wx.wxFLEX_GROWMODE_SPECIFIED )

UI.m_staticText2 = wx.wxStaticText( UI.MyDialog1, wx.wxID_ANY, "MyLabel", wx.wxDefaultPosition, wx.wxDefaultSize, 0 )
UI.m_staticText2:Wrap( -1 )
UI.fgSizer3:Add( UI.m_staticText2, 0, wx.wxALL, 5 )

UI.m_button3 = wx.wxButton( UI.MyDialog1, wx.wxID_ANY, "MyButton", wx.wxDefaultPosition, wx.wxDefaultSize, 0 )
UI.fgSizer3:Add( UI.m_button3, 0, wx.wxALL, 5 )

UI.m_staticText3 = wx.wxStaticText( UI.MyDialog1, wx.wxID_ANY, "MyLabel", wx.wxDefaultPosition, wx.wxDefaultSize, 0 )
UI.m_staticText3:Wrap( -1 )
UI.fgSizer3:Add( UI.m_staticText3, 0, wx.wxALL, 5 )

UI.m_button4 = wx.wxButton( UI.MyDialog1, wx.wxID_ANY, "MyButton", wx.wxDefaultPosition, wx.wxDefaultSize, 0 )
UI.fgSizer3:Add( UI.m_button4, 0, wx.wxALL, 5 )

UI.fgSizer4 = wx.wxFlexGridSizer( 0, 2, 0, 0 )
UI.fgSizer4:SetFlexibleDirection( wx.wxBOTH )
UI.fgSizer4:SetNonFlexibleGrowMode( wx.wxFLEX_GROWMODE_SPECIFIED )

UI.m_grid2 = wx.wxGrid( UI.MyDialog1, wx.wxID_ANY, wx.wxDefaultPosition, wx.wxDefaultSize, 0 )

-- Grid
UI.m_grid2:CreateGrid( 5, 5 )
UI.m_grid2:EnableEditing( True )
UI.m_grid2:EnableGridLines( True )
UI.m_grid2:EnableDragGridSize( False )
UI.m_grid2:SetMargins( 0, 0 )

-- Columns
UI.m_grid2:EnableDragColSize( True )
UI.m_grid2:SetColLabelSize( 30 )
UI.m_grid2:SetColLabelAlignment( wx.wxALIGN_CENTRE, wx.wxALIGN_CENTRE )

-- Rows
UI.m_grid2:EnableDragRowSize( True )
UI.m_grid2:SetRowLabelSize( 80 )
    UI.m_grid2:EnableEditing( True )
UI.m_grid2:SetRowLabelAlignment( wx.wxALIGN_CENTRE, wx.wxALIGN_CENTRE )

-- Label Appearance

-- Cell Defaults
UI.m_grid2:SetDefaultCellAlignment( wx.wxALIGN_LEFT, wx.wxALIGN_TOP )
UI.fgSizer4:Add( UI.m_grid2, 0, wx.wxALL, 5 )


UI.fgSizer3:Add( UI.fgSizer4, 1, wx.wxEXPAND, 5 )


UI.MyDialog1:SetSizer( UI.fgSizer3 )
UI.MyDialog1:Layout()

   CreateLables(5)


UI.m_grid2:Connect(wx.wxEVT_GRID_CELL_LEFT_CLICK,
    function(event)
        wx.wxMessageBox("Based on the C++ version by Marco Ghislanzoni.\n"..
                        wxlua.wxLUA_VERSION_STRING.." built with "..wx.wxVERSION_STRING,
                        "About wxLua Temperature Converter",
                        wx.wxOK + wx.wxICON_INFORMATION,
                        UI.MyDialog1)
    end)

UI.MyDialog1:Centre( wx.wxBOTH )

UI.MyDialog1:Show()

wx.wxGetApp():MainLoop()
    /code]

Offline DBK

*
  •  9 9
    • View Profile
Re: wxLua and wxWidgets questions
« Reply #5 on: December 01, 2017, 07:44:47 PM »
I am able to create grids, populate them and manage them quite extensively.  My only issue is related to retrieving, from the grid object, information about what somewhat "complex" cell selections the user might have made.

Instead of posting my whole program here, I only posted a sample app with some of my code relevant to the problem at hand to allow others to offer possible insight as to how I've gone wrong in my attempts.  I do, however, really appreciate your attempts to help me. Unfortunately, I knew (and stated as such in my first post) that I might have trouble locating someone with the knowledge and/or experience to solve this one. Especially as I believe this one is a bug in wxLua itself.  I was hopeful that somebody had used the grid functions in question and could easily tell me how I messed up.

Best regards,  David

Offline gorf23

*
  •  183 183
    • View Profile
Re: wxLua and wxWidgets questions
« Reply #6 on: December 02, 2017, 03:53:27 PM »
from what I can tell from what you posted is the getrow() and getcol() is where the program is crashing...

I haven't seen a way to use them in lua, I think you need to use wxgridevent  for getrow and getcol but haven't figured out a way in lua

but I am sure its possible

Offline DBK

*
  •  9 9
    • View Profile
Re: wxLua and wxWidgets questions
« Reply #7 on: December 02, 2017, 04:37:24 PM »
Here is the "wxLua 2.8.12.2 Reference Manual for wxWidgets 2.8.12": http://wxlua.sourceforge.net/docs/wxluaref.html

If you search for, or scroll down to wxGridCellCoordsArray, you will see that wxLua wrappers take care of this.  Presumably because they return c++ style arrays in userdatat that can't be used directly by Lua (somebody correct me if I have this wrong).
Clicking on the link in the first column will take you to the information I muddled through because I don't fully understand it yet.  But I was able to get the GetCount() function (returns an integer) to return good data as verified with testing.  If I drag-select three blocks on the grid, Get_Count returns 3, two returns 2, etc.

I can't figure out how to call the Item() function which should return a wxGridCellCoords array (again not Lua compatible). The wxGridCellCoords is defined directly above wxGridCellCoordsArray in the Reference Manual.

For me, it is crashing the wxLuaEditor on the Item() call because I have commented out the GetRow() and GetCol() lines. 

Because I couldn't find any wxLua examples that use these particular functions, I  searched the Reference Manual to find other instances of a function returning an array of arrays. Hoping that a less obscure function might do so and be in some example code that I could look at.  No luck on that front as this function appears to be the only case.   

Offline DBK

*
  •  9 9
    • View Profile
Re: wxLua and wxWidgets questions
« Reply #8 on: December 02, 2017, 05:39:56 PM »
The way you are referring to getrow() and getcol() in your posts points out my failure to accurately describe what I am trying to do.

I'll try again, referring you back to the picture of the gird in my first post.

I didn't show the whole grid, so we have no row and column headers to refer to, so I will refer to the contents of the cells.  You can see I selected two blocks, one from 28.40 down to 46.77 (2 x4) and the other is from 5.78 down to 41.19 (2 x 3).  I am trying to get the grid to tell my program what blocks the user selected, so that the contents of all the selected cells can programatically be replaced with a given value, say "0.0" for instance.  It's a time saving shortcut to save the user from manually having to change each value to "0.0", one at a time.
 
In wxWidgets, the way that is done is through the  wxGridCellCoordsArray and  wxGridCellCoords classes and their methods. The wxGridCellCoords class contains the methods GetRow and GetCol that will provide the information I need.  In the example grid, the correct calls should return the row# and column# of the two toplefts (28.49 and 5.78) and the two bottomrights (46.77 and 41.19).

Offline DBK

*
  •  9 9
    • View Profile
Re: wxLua and wxWidgets questions
« Reply #9 on: December 17, 2017, 04:58:07 AM »
I thought I would take another stab at it and figured out what I was doing wrong in just a couple minutes of testing.  I thought I would post some test code in case others would like to see what I was trying to explain.

Below is a complete Lua example.  You should be able to copy it into the mcLuaEditor and run it without doing anything but saving it. After running it, hold the ctrl-key down while drag selecting a couple times and maybe a couple single selections. Then just type in a numeric value and hit enter. Keep in mind, it is a simple demo and does not check to make sure your selections are all the same data type.  The XY columns are floating point only and all the others are text.  You can cause errors in some selection cases that include text columns , but only because I didn't try to handle them appropriately for this demo.

Code: [Select]
-----------------------------------------------------------------------------
-- Name:        gridblocktest.wx.lua
-- Purpose:     Show how to use the Grid Block Selections to fill all with data at once
-- Author:      David Kenny, from original code by J Winwood
-----------------------------------------------------------------------------

-- Load the wxLua module, does nothing if running from wxLua, wxLuaFreeze, or wxLuaEdit
package.cpath = package.cpath..";./?.dll;./?.so;../lib/?.so;../lib/vc_dll/?.dll;../lib/bcc_dll/?.dll;../lib/mingw_dll/?.dll;"
require("wx")

local frame = wx.wxFrame(wx.NULL, wx.wxID_ANY, "Grid Block-Selection example",
                         wx.wxPoint(25, 25), wx.wxSize(450, 450))

local fileMenu = wx.wxMenu("", wx.wxMENU_TEAROFF)
fileMenu:Append(wx.wxID_EXIT, "E&xit\tCtrl-X", "Quit the program")


frame:Connect(wx.wxID_EXIT, wx.wxEVT_COMMAND_MENU_SELECTED,
    function (event)
        frame:Close()
    end )


grid = wx.wxGrid(frame, wx.wxID_ANY)

grid:Connect( wx.wxEVT_KEY_DOWN, function(event)
--implements PartsLocGridOnKeyDown
      BTL = (grid:GetSelectionBlockTopLeft())   
      BBR = (grid:GetSelectionBlockBottomRight())   
      SCs = (grid:GetSelectedCells())
--Have to grab the selections before the CELL_CHANGE as that cancels the selection
event:Skip()
end )

grid:Connect( wx.wxEVT_GRID_CELL_CHANGE, function(event)
                                                                  --implements PartsLocGridOnGridCmdCellChange
      Row = event:GetRow()
      Col = event:GetCol()
      if Col > 0 then
        Num = tonumber(grid:GetCellValue(Row, Col)) -- Floating point
        if Num == nil then Num = 0 end
        Num = string.format("%04.2f", Num)
        grid:SetCellValue( Row, Col, Num)
      end
     
      --Made no attempt (in this demo) to make sure the selected blocks are in columns with the same data type
      --Now Copy the contents to all blocks and single selections using the selection arrays grabbed durint the KEY_DOWN event.
      print("BTL Count:".. BTL:GetCount())
      for i=0,BTL:GetCount()-1 do
        local wxGridCellCoords topleft = (BTL:Item(i))
        local wxGridCellCoords bottomright = (BBR:Item(i))
        tlr = topleft:GetRow()
        tlc = topleft:GetCol()
        brr = bottomright:GetRow()
        brc = bottomright:GetCol()   
        FillBlock(tlr, tlc, brr, brc, Num)
      end
      for i=0, SCs:GetCount()-1 do
        local wxGridCellCoords selectedcells = (SCs:Item(i))
        scr = selectedcells:GetRow()
        scc = selectedcells:GetCol()
        grid:SetCellValue(scr, scc, Num)
       
      end  event:Skip()
end )

 
grid:CreateGrid(10, 8)
grid:SetColSize(3, 200)

grid:SetColLabelValue(0,"Description" )
grid:SetColLabelValue(1,"Center x" )
grid:SetColLabelValue(2,"Center y" )
grid:SetColFormatFloat(1,4,2)
grid:SetColFormatFloat(2,4,2)

for i=0, 10 do   --Create some rows to work with
  --local str = "Hole #"..i
  grid:SetCellValue(i,0,string.format("Hole #%s",i))
end 

frame:Show(true)

BTL = nil
BBR = nil
SCs = nil

function FillBlock(tlr, tlc, brr, brc, val)
  for i=tlr, brr do
    for j=tlc, brc do
      grid:SetCellValue(i, j, val) 
    end
  end 
end


-- Call wx.wxGetApp():MainLoop() last to start the wxWidgets event loop,
-- otherwise the wxLua program will exit immediately.
-- Does nothing if running from wxLua, wxLuaFreeze, or wxLuaEdit since the
-- MainLoop is already running or will be started by the C++ program.
wx.wxGetApp():MainLoop()

BTW, the error was simply not realizing that the returned arrays are indexed from 0 to getcount-1 instead of 1 to getcount. So it blew-up whenever the index was out of range.