2012-08-31 14:46:33 -06:00
-- Interface powered item editor.
local gui = require ' gui '
2012-09-07 08:25:39 -06:00
local dialog = require ' gui.dialogs '
2012-11-28 12:13:42 -07:00
local widgets = require ' gui.widgets '
2012-09-23 14:45:19 -06:00
local args = { ... }
2012-11-28 12:13:42 -07:00
local keybindings = {
offset = { key = " CUSTOM_ALT_O " , desc = " Show current items offset " } ,
find = { key = " CUSTOM_F " , desc = " Find a value by entering a predicate " } ,
lua_set = { key = " CUSTOM_ALT_S " , desc = " Set by using a lua function " } ,
insert = { key = " CUSTOM_ALT_I " , desc = " Insert a new value to the vector " } ,
delete = { key = " CUSTOM_ALT_D " , desc = " Delete selected entry " } ,
help = { key = " HELP " , desc = " Show this help " } ,
}
2012-09-23 14:45:19 -06:00
function getTargetFromScreens ( )
local my_trg
if dfhack.gui . getCurFocus ( ) == ' item ' then
my_trg = dfhack.gui . getCurViewscreen ( ) . item
elseif dfhack.gui . getCurFocus ( ) == ' joblist ' then
local t_screen = dfhack.gui . getCurViewscreen ( )
my_trg = t_screen.jobs [ t_screen.cursor_pos ]
elseif dfhack.gui . getCurFocus ( ) == ' createquota ' then
local t_screen = dfhack.gui . getCurViewscreen ( )
my_trg = t_screen.orders [ t_screen.sel_idx ]
elseif dfhack.gui . getCurFocus ( ) == ' dwarfmode/LookAround/Flow ' then
local t_look = df.global . ui_look_list.items [ df.global . ui_look_cursor ]
my_trg = t_look.flow
2012-08-31 14:46:33 -06:00
2012-09-23 14:45:19 -06:00
elseif dfhack.gui . getSelectedUnit ( true ) then
my_trg = dfhack.gui . getSelectedUnit ( true )
elseif dfhack.gui . getSelectedItem ( true ) then
my_trg = dfhack.gui . getSelectedItem ( true )
elseif dfhack.gui . getSelectedJob ( true ) then
my_trg = dfhack.gui . getSelectedJob ( true )
else
qerror ( " No valid target found " )
end
return my_trg
2012-08-31 14:46:33 -06:00
end
2012-09-23 14:22:14 -06:00
GmEditorUi = defclass ( GmEditorUi , gui.FramedScreen )
GmEditorUi.ATTRS = {
2012-08-31 14:46:33 -06:00
frame_style = gui.GREY_LINE_FRAME ,
frame_title = " GameMaster's editor " ,
}
2012-11-28 12:13:42 -07:00
function GmEditorUi : onHelp ( )
self.subviews . pages : setSelected ( 2 )
end
function burning_red ( input ) -- todo does not work! bug angavrilov that so that he would add this, very important!!
local col = COLOR_LIGHTRED
return { text = input , pen = dfhack.pen . parse { fg = COLOR_LIGHTRED , bg = 0 } }
end
2012-11-28 17:26:10 -07:00
function Disclaimer ( tlb )
local dsc = { " Association Of " , { text = " Psychic " , pen = dfhack.pen . parse { fg = COLOR_YELLOW , bg = 0 } } ,
" Dwarves (AOPD) is not responsible for all the damage " , NEWLINE , " that this tool can (and will) cause to you and your loved dwarves " , NEWLINE , " and/or saves.Please use with caution. " , NEWLINE , { text = " Magma not included. " , pen = dfhack.pen . parse { fg = COLOR_LIGHTRED , bg = 0 } } }
if tlb then
for _ , v in ipairs ( dsc ) do
table.insert ( tlb , v )
end
end
return dsc
end
2012-09-23 14:22:14 -06:00
function GmEditorUi : init ( args )
self.stack = { }
self.item_count = 0
self.keys = { }
2012-11-28 12:13:42 -07:00
local helptext = { { text = " Help " } , NEWLINE , NEWLINE }
for k , v in pairs ( keybindings ) do
table.insert ( helptext , { text = v.desc , key = v.key , key_sep = ' : ' } )
table.insert ( helptext , NEWLINE )
end
table.insert ( helptext , NEWLINE )
2012-11-28 17:26:10 -07:00
Disclaimer ( helptext )
2012-09-23 14:22:14 -06:00
2012-11-28 12:13:42 -07:00
local helpPage = widgets.Panel {
subviews = { widgets.Label { text = helptext , frame = { l = 1 , t = 1 , yalign = 0 } } } }
local mainList = widgets.List { view_id = " list_main " , choices = { } , frame = { l = 1 , t = 3 , yalign = 0 } , on_submit = self : callback ( " editSelected " ) ,
text_pen = dfhack.pen . parse { fg = COLOR_DARKGRAY , bg = 0 } , cursor_pen = dfhack.pen . parse { fg = COLOR_YELLOW , bg = 0 } }
local mainPage = widgets.Panel {
subviews = {
mainList ,
2012-11-29 02:13:26 -07:00
widgets.Label { text = { { text = " <no item> " , id = " name " } , { gap = 1 , text = " Help " , key = " HELP " , key_sep = ' () ' } } , view_id = ' lbl_current_item ' , frame = { l = 1 , t = 1 , yalign = 0 } } ,
2012-11-28 12:13:42 -07:00
--widgets.Label{text="BLAH2"}
}
, view_id = ' page_main ' }
local pages = widgets.Pages { subviews = { mainPage , helpPage } , view_id = " pages " }
self : addviews {
pages
}
self : pushTarget ( args.target )
2012-09-23 14:22:14 -06:00
end
2012-10-07 11:44:18 -06:00
function GmEditorUi : find ( test )
local trg = self : currentTarget ( )
2012-11-28 12:13:42 -07:00
if test == nil then
dialog.showInputPrompt ( " Test function " , " Input function that tests(k,v as argument): " , COLOR_WHITE , " " , dfhack.curry ( self.find , self ) )
return
end
local e , what = load ( " return function(k,v) return " .. test .. " end " )
if e == nil then
dialog.showMessage ( " Error! " , " function failed to compile \n " .. what , COLOR_RED )
end
2012-10-07 11:44:18 -06:00
if trg.target and trg.target . _kind and trg.target . _kind == " container " then
2012-11-28 12:13:42 -07:00
2012-10-07 11:44:18 -06:00
for k , v in pairs ( trg.target ) do
if e ( ) ( k , v ) == true then
self : pushTarget ( v )
return
end
end
2012-11-28 12:13:42 -07:00
else
local i = 1
for k , v in pairs ( trg.target ) do
if e ( ) ( k , v ) == true then
self.subviews . list_main : setSelected ( i )
return
end
i = i + 1
end
2012-10-07 11:44:18 -06:00
end
end
2012-09-23 14:22:14 -06:00
function GmEditorUi : insertNew ( typename )
local tp = typename
if typename == nil then
2012-11-28 12:13:42 -07:00
dialog.showInputPrompt ( " Class type " , " Input class type: " , COLOR_WHITE , " " , self : callback ( " insertNew " ) )
2012-09-23 14:22:14 -06:00
return
end
local ntype = df [ tp ]
if ntype == nil then
dialog.showMessage ( " Error! " , " Type ' " .. tp .. " not found " , COLOR_RED )
return
end
local trg = self : currentTarget ( )
if trg.target and trg.target . _kind and trg.target . _kind == " container " then
local thing = ntype : new ( )
2012-11-28 12:13:42 -07:00
dfhack.call_with_finalizer ( 1 , false , df.delete , thing , function ( tscreen , target , to_insert )
target : insert ( " # " , to_insert ) ; tscreen : updateTarget ( true , true ) ; end , self , trg.target , thing )
2012-09-23 14:22:14 -06:00
end
end
2012-11-28 12:13:42 -07:00
function GmEditorUi : deleteSelected ( key )
2012-09-23 14:22:14 -06:00
local trg = self : currentTarget ( )
if trg.target and trg.target . _kind and trg.target . _kind == " container " then
2012-11-28 12:13:42 -07:00
trg.target : erase ( key )
self : updateTarget ( true , true )
2012-09-23 14:22:14 -06:00
end
end
2012-11-28 12:13:42 -07:00
function GmEditorUi : getSelectedKey ( )
return self : currentTarget ( ) . keys [ self.subviews . list_main : getSelected ( ) ]
end
2012-09-23 14:22:14 -06:00
function GmEditorUi : currentTarget ( )
return self.stack [ # self.stack ]
end
2012-11-28 12:13:42 -07:00
function GmEditorUi : editSelected ( index , choice )
2012-09-23 14:22:14 -06:00
local trg = self : currentTarget ( )
2012-11-28 12:13:42 -07:00
local trg_key = trg.keys [ index ]
2012-09-23 14:22:14 -06:00
if trg.target and trg.target . _kind and trg.target . _kind == " bitfield " then
2012-11-28 12:13:42 -07:00
trg.target [ trg_key ] = not trg.target [ trg_key ]
self : updateTarget ( true )
2012-09-23 14:22:14 -06:00
else
--print(type(trg.target[trg.keys[trg.selected]]),trg.target[trg.keys[trg.selected]]._kind or "")
2012-11-28 12:13:42 -07:00
local trg_type = type ( trg.target [ trg_key ] )
2012-09-23 14:22:14 -06:00
if trg_type == ' number ' or trg_type == ' string ' then --ugly TODO: add metatable get selected
2012-11-28 12:13:42 -07:00
dialog.showInputPrompt ( trg_key , " Enter new value: " , COLOR_WHITE ,
tostring ( trg.target [ trg_key ] ) , self : callback ( " commitEdit " , trg_key ) )
2012-09-23 14:22:14 -06:00
elseif trg_type == ' boolean ' then
2012-11-28 12:13:42 -07:00
trg.target [ trg_key ] = not trg.target [ trg_key ]
self : updateTarget ( true )
2012-09-23 14:22:14 -06:00
elseif trg_type == ' userdata ' then
2012-11-28 12:13:42 -07:00
self : pushTarget ( trg.target [ trg_key ] )
2012-09-23 14:22:14 -06:00
else
print ( " Unknow type: " .. trg_type )
2012-11-28 12:13:42 -07:00
print ( " Subtype: " .. tostring ( trg.target [ trg_key ] . _kind ) )
2012-09-23 14:22:14 -06:00
end
end
end
2012-11-28 12:13:42 -07:00
function GmEditorUi : commitEdit ( key , value )
2012-09-23 14:22:14 -06:00
local trg = self : currentTarget ( )
2012-11-28 12:13:42 -07:00
if type ( trg.target [ key ] ) == ' number ' then
trg.target [ key ] = tonumber ( value )
elseif type ( trg.target [ key ] ) == ' string ' then
trg.target [ key ] = value
2012-09-23 14:22:14 -06:00
end
2012-11-28 12:13:42 -07:00
self : updateTarget ( true )
2012-11-28 08:40:37 -07:00
end
2012-11-28 12:13:42 -07:00
function GmEditorUi : set ( key , input )
2012-11-28 08:40:37 -07:00
local trg = self : currentTarget ( )
if input == nil then
2012-11-28 12:13:42 -07:00
dialog.showInputPrompt ( " Set to what? " , " Lua code to set to (v cur target): " , COLOR_WHITE , " " , self : callback ( " set " , key ) )
2012-11-28 08:40:37 -07:00
return
end
local e , what = load ( " return function(v) return " .. input .. " end " )
if e == nil then
dialog.showMessage ( " Error! " , " function failed to compile \n " .. what , COLOR_RED )
2012-11-28 12:13:42 -07:00
return
2012-11-28 08:40:37 -07:00
end
2012-11-28 12:13:42 -07:00
trg.target [ key ] = e ( ) ( trg )
self : updateTarget ( true )
2012-09-23 14:22:14 -06:00
end
2012-11-28 12:13:42 -07:00
function GmEditorUi : onInput ( keys )
if keys.LEAVESCREEN then
if self.subviews . pages : getSelected ( ) == 2 then
self.subviews . pages : setSelected ( 1 )
else
2012-09-23 14:22:14 -06:00
self : popTarget ( )
end
2012-11-28 12:13:42 -07:00
elseif keys [ keybindings.offset . key ] then
local trg = self : currentTarget ( )
local size , off = df.sizeof ( trg.target : _field ( trg.keys [ trg.selected ] ) )
dialog.showMessage ( " Offset " , string.format ( " Size hex=%x,%x dec=%d,%d " , size , off , size , off ) , COLOR_WHITE )
--elseif keys.CUSTOM_ALT_F then --filter?
elseif keys [ keybindings.find . key ] then
self : find ( )
elseif keys [ keybindings.lua_set . key ] then
self : set ( self : getSelectedKey ( ) )
--elseif keys.CUSTOM_I then
-- self:insertSimple()
elseif keys [ keybindings.insert . key ] then --insert
self : insertNew ( )
elseif keys [ keybindings.delete . key ] then --delete
self : deleteSelected ( self : getSelectedKey ( ) )
end
self.super . onInput ( self , keys )
end
function GmEditorUi : updateTarget ( preserve_pos , reindex )
local trg = self : currentTarget ( )
if reindex then
trg.keys = { }
for k , v in pairs ( trg.target ) do
table.insert ( trg.keys , k )
2012-09-23 14:22:14 -06:00
end
end
2012-11-28 12:13:42 -07:00
self.subviews . lbl_current_item : itemById ( ' name ' ) . text = tostring ( trg.target )
local t = { }
for k , v in pairs ( trg.keys ) do
2012-11-29 02:13:26 -07:00
table.insert ( t , { text = { { text = string.format ( " %-25s " , tostring ( v ) ) } , { gap = 1 , text = tostring ( trg.target [ v ] ) , } } } )
2012-11-28 12:13:42 -07:00
end
local last_pos
if preserve_pos then
last_pos = self.subviews . list_main : getSelected ( )
end
self.subviews . list_main : setChoices ( t )
if last_pos then
self.subviews . list_main : setSelected ( last_pos )
else
self.subviews . list_main : setSelected ( 1 )
end
2012-09-23 14:22:14 -06:00
end
function GmEditorUi : pushTarget ( target_to_push )
local new_tbl = { }
new_tbl.target = target_to_push
new_tbl.keys = { }
new_tbl.selected = 1
for k , v in pairs ( target_to_push ) do
table.insert ( new_tbl.keys , k )
end
new_tbl.item_count =# new_tbl.keys
table.insert ( self.stack , new_tbl )
2012-11-28 12:13:42 -07:00
self : updateTarget ( )
2012-09-23 14:22:14 -06:00
end
function GmEditorUi : popTarget ( )
table.remove ( self.stack ) --removes last element
if # self.stack == 0 then
self : dismiss ( )
2012-11-28 12:13:42 -07:00
return
2012-09-23 14:22:14 -06:00
end
2012-11-28 12:13:42 -07:00
self : updateTarget ( )
2012-09-23 14:22:14 -06:00
end
2012-09-23 14:45:19 -06:00
function show_editor ( trg )
local screen = GmEditorUi { target = trg }
screen : show ( )
end
if # args ~= 0 then
if args [ 1 ] == " dialog " then
function thunk ( entry )
local t = load ( " return " .. entry ) ( )
show_editor ( t )
end
dialog.showInputPrompt ( " Gm Editor " , " Object to edit: " , COLOR_GRAY , " " , thunk )
else
local t = load ( " return " .. args [ 1 ] ) ( )
show_editor ( t )
end
else
show_editor ( getTargetFromScreens ( ) )
end
2012-08-31 14:46:33 -06:00