It'll either show nothing or show the frame, but not the graphics in it. The latter happens if the graphics aren't loaded in properly.
At the very least, there should be no situation where it crashes.
EDIT:
--Written by Putnam
local widgets=require('gui.widgets')
local gui=require('gui')
local dlg=require('gui.dialogs')
local GraphicalButton=defclass(GraphicalButton,widgets.Widget)
GraphicalButton.ATTRS={
on_click = DEFAULT_NIL,
on_rclick = DEFAULT_NIL,
graphic = DEFAULT_NIL, --refers to the name of a tilepage
label = DEFAULT_NIL
}
function GraphicalButton:preUpdateLayout()
self.frame=self.frame or {}
if not self.page then self.frame.w=0 self.frame.h=0 return end
self.frame.w=self.page.page_dim_x
self.frame.h=self.page.page_dim_y
end
function GraphicalButton:onRenderBody(dc)
if not self.page then return end
for k,v in ipairs(self.page.texpos) do
dc:seek(k%self.frame.w,math.floor(k/self.frame.w)):tile(32,v)
end
end
function GraphicalButton:onInput(keys)
if keys._MOUSE_L_DOWN and self:getMousePos() and self.on_click then
self.on_click()
end
if keys._MOUSE_R_DOWN and self:getMousePos() and self.on_rclick then
self.on_rclick()
end
end
function GraphicalButton:init(args)
if not self.graphic then return end
for k,v in ipairs(df.global.texture.page) do
if v.token==self.graphic then self.page=v return end
end
error('No tilepage found: '..self.graphic)
end
local GraphicsBox=defclass(GraphicsBox,dlg.MessageBox)
GraphicsBox.ATTRS{
frame_style = gui.GREY_LINE_FRAME,
frame_inset = 1,
-- new attrs
on_accept = DEFAULT_NIL,
on_cancel = DEFAULT_NIL,
on_close = DEFAULT_NIL,
}
function GraphicsBox:onRender()
self.super.onRender(self)
self:renderSubviews()
end
function GraphicsBox:getWantedFrameSize()
local button=self.subviews.image
if not button.frame then return end
return button.frame.w,button.frame.h
end
function GraphicsBox:init(info)
self:addviews{
GraphicalButton{
view_id = 'image',
graphic = info.graphic,
frame = {l=0,t=0}
}
}
end
function showImage(title,image,on_close)
GraphicsBox{
frame_title=title,
graphic=image,
on_close=on_close
}:show()
end
local lastFrame=df.global.enabler.frame_last
dfhack.onStateChange.itemPictures=function(code)
if code==SC_VIEWSCREEN_CHANGED and dfhack.isWorldLoaded() then
if dfhack.gui.getCurViewscreen()._type==df.viewscreen_textviewerst and df.global.enabler.frame_last-lastFrame>df.global.enabler.gfps*20 then
lastFrame=df.global.enabler.frame_last
local parent=dfhack.gui.getCurViewscreen().parent
if parent._type==df.viewscreen_unitst or parent._type==df.viewscreen_dungeon_monsterstatusst then
local unit=parent.unit
local imageExists=false
local creature=df.creature_raw.find(unit)
for k,v in ipairs(df.global.texture.page) do
if v.token==creature.creature_id..'_TEXT_IMAGE' and v.loaded then
imageExists=true
break
end
end
if imageExists then
showImage("Image",creature.creature_id..'_TEXT_IMAGE')
end
elseif parent._type==df.viewscreen_itemst then
local item=parent.item
local imageExists=false
local itemName=''
local subtype=dfhack.items.getSubtypeDef(item:getType(),item:getSubtype())
if subtype then
itemName=df.item_type[item:getType()]..'/'..subtype.id --gotta be a slash methinks
else
itemName=df.item_type[item:getType()]
end
for k,v in ipairs(df.global.texture.page) do
if v.token==itemName..'_TEXT_IMAGE' and v.loaded then
imageExists=true
break
end
end
if imageExists then
showImage("Image",itemName..'_TEXT_IMAGE')
end
end
end
end
end
This version will just ignore any non-loaded graphics.