Graphical Remote Lua Debugger, a debugger for the lua programming language.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

211 lines
6.0 KiB

-- see copyright notice in wxLdb.lua
local print = print
local wx = require( "wx" )
_G.print = print -- override wx print function with original one
local mainthread = require( "mainthread" )
local assert = assert
local setmetatable = setmetatable
local getmetatable = getmetatable
local string = string
local tostring = tostring
local pairs = pairs
local ipairs = ipairs
local table = table
local type = type
local next = next
module( "ui.luaExplorer" )
local meta = { __index = {} }
local evaluableItemMeta = { __index = {} }
local promptString = "<type new expression here>"
local function escapeString( str )
for i = 1, #str do
if string.sub( str, i, i ) == "\000" then
str = string.sub( str, 1, i-1 ).."(NULL)"..string.sub( str, i+1 )
end
end
return str
end
function new( parent, interactive )
local self = { interactive = interactive }
setmetatable( self, meta )
local flags = wx.wxTR_HIDE_ROOT + wx.wxTR_LINES_AT_ROOT + wx.wxTR_HAS_BUTTONS
if interactive then flags = flags + wx.wxTR_EDIT_LABELS end
self.tree = wx.wxTreeCtrl( parent, wx.wxID_ANY, wx.wxDefaultPosition, wx.wxDefaultSize, flags )
self.root = self.tree:AddRoot( "root" )
self.complexValues = {}
self.tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_EXPANDING, function( event ) self:onExpanding_( event ) end )
self.tree:Connect( wx.wxEVT_COMMAND_TREE_ITEM_COLLAPSED, function( event ) self:onCollapsed_( event ) end )
if interactive then
self.tree:Connect( wx.wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, function( event ) self:onBeginEdit_( event ) end )
self.tree:Connect( wx.wxEVT_COMMAND_TREE_END_LABEL_EDIT, function( event ) self:onEdited_( event ) end )
self.tree:Connect( wx.wxEVT_COMMAND_TREE_KEY_DOWN, function( event ) self:onKeyDown_( event ) end )
self.tree:AppendItem( self.root, promptString )
end
return self
end
function meta.__index:getRoot()
return self.tree
end
function meta.__index:setData( data )
self:releaseHierarchy_( self.root )
assert( next( self.complexValues ) == nil )
--for _, cval in pairs( self.complexValues ) do
-- cval:release()
--end
--self.complexValues = {}
self.tree:DeleteChildren( self.root )
if data ~= nil then
for _, entry in ipairs( data ) do
self:append_( self.root, entry )
end
end
end
function meta.__index:append_( parent, entry )
local value
local t = type( entry.value )
local isComplex = false
if t == "table" then
value = entry.value.short
if value ~= nil and (entry.value.type == "string" or entry.value.type == "proxy") then
value = escapeString( value )
end
if entry.value.id ~= nil then
isComplex = true
end
elseif t == "string" then
value = "\""..escapeString( entry.value ).."\""
elseif t == "nil" then
value = nil
else
value = tostring( entry.value )
end
local node
if value == nil then
node = self.tree:AppendItem( parent, entry.name )
else
node = self.tree:AppendItem( parent, entry.name.." = "..value )
end
if isComplex then
self.tree:SetItemHasChildren( node, true )
self.complexValues[node:GetValue()] = entry.value
end
end
function meta.__index:onExpanding_( event )
local item = event:GetItem()
local cval = assert( self.complexValues[item:GetValue()] )
local value = cval:get()
for _, entry in ipairs( value ) do
self:append_( item, entry )
end
end
function meta.__index:onCollapsed_( event )
local item = event:GetItem()
self:releaseHierarchy_( item )
self.tree:DeleteChildren( item )
self.tree:SetItemHasChildren( item, true )
end
function meta.__index:releaseHierarchy_( item )
local child = self.tree:GetFirstChild( item )
while child:IsOk() do
local cval = self.complexValues[child:GetValue()]
if cval ~= nil then
cval:release()
self.complexValues[child:GetValue()] = nil
end
self:releaseHierarchy_( child )
child = self.tree:GetNextSibling( child )
end
end
function meta.__index:refresh()
assert( self.interactive )
local exprItem = self.tree:GetFirstChild( self.root )
while exprItem:IsOk() do
self:releaseHierarchy_( exprItem )
self.tree:Collapse( exprItem )
self.tree:DeleteChildren( exprItem )
if self.complexValues[exprItem:GetValue()] ~= nil then
self.tree:SetItemHasChildren( exprItem, true )
end
exprItem = self.tree:GetNextSibling( exprItem )
end
for _, cval in pairs( self.complexValues ) do
assert( getmetatable( cval ) == evaluableItemMeta ) -- all other values should have been released
end
end
function meta.__index:clear()
local item = self.root
self:releaseHierarchy_( item )
self.tree:DeleteChildren( item )
end
function meta.__index:onBeginEdit_( event )
local item = event:GetItem()
local parent = self.tree:GetItemParent( item )
if parent:GetValue() ~= self.root:GetValue() then
event:Veto() -- only direct children of root can be edited
end
end
function meta.__index:onEdited_( event )
local item = event:GetItem()
assert( self.tree:GetItemParent( item ):GetValue() == self.root:GetValue() )
self:releaseHierarchy_( item )
self.tree:Collapse( item )
self.tree:DeleteChildren( item )
local expr = event:GetLabel()
local cval = { evaluate = function() return self.evaluateCallback( expr ) end }
setmetatable( cval, evaluableItemMeta )
self.complexValues[item:GetValue()] = cval
self.tree:SetItemHasChildren( item, true )
if self.tree:GetLastChild( self.root ):GetValue() == item:GetValue() then
self.tree:AppendItem( self.root, promptString )
end
self.tree:Expand( item )
end
function meta.__index:onKeyDown_( event )
if event:GetKeyCode() == wx.WXK_DELETE then
local item = self.tree:GetSelection()
if item:IsOk() then
local parent = self.tree:GetItemParent( item )
if parent:GetValue() == self.root:GetValue() and item:GetValue() ~= self.tree:GetLastChild( self.root ):GetValue() then
self:releaseHierarchy_( item )
self.tree:Delete( item )
end
end
end
end
function evaluableItemMeta.__index:get()
return self.evaluate()
end
function evaluableItemMeta.__index:release()
-- nothing to do
end