From 471d15ba4cd0ea3676d8bc0dd1d96de8e55d0886 Mon Sep 17 00:00:00 2001 From: Warmist Date: Thu, 29 Nov 2012 20:49:16 +0200 Subject: [PATCH] New building selection dialog. --- library/lua/gui/buildings.lua | 268 ++++++++++++++++++++++++++++++++++ scripts/gui/advfort.lua | 57 ++------ 2 files changed, 280 insertions(+), 45 deletions(-) create mode 100644 library/lua/gui/buildings.lua diff --git a/library/lua/gui/buildings.lua b/library/lua/gui/buildings.lua new file mode 100644 index 000000000..98bee3be5 --- /dev/null +++ b/library/lua/gui/buildings.lua @@ -0,0 +1,268 @@ +-- Stock dialog for selecting buildings + +local _ENV = mkmodule('gui.buildings') + +local gui = require('gui') +local widgets = require('gui.widgets') +local dlg = require('gui.dialogs') +local utils = require('utils') + +ARROW = string.char(26) + +WORKSHOP_ABSTRACT={ + [df.building_type.Civzone]=true,[df.building_type.Stockpile]=true, +} +WORKSHOP_SPECIAL={ + [df.building_type.Workshop]=true,[df.building_type.Furnace]=true,[df.building_type.Trap]=true, + [df.building_type.Construction]=true +} +BuildingDialog = defclass(BuildingDialog, gui.FramedScreen) + +BuildingDialog.focus_path = 'BuildingDialog' + +BuildingDialog.ATTRS{ + prompt = 'Type or select a building from this list', + frame_style = gui.GREY_LINE_FRAME, + frame_inset = 1, + frame_title = 'Select Building', + -- new attrs + none_caption = 'none', + hide_none = false, + use_abstract = true, + use_workshops = true, + use_tool_workshop=true, + use_furnace = true, + use_construction = true, + use_trap = true, + use_custom = true, + building_filter = DEFAULT_NIL, + on_select = DEFAULT_NIL, + on_cancel = DEFAULT_NIL, + on_close = DEFAULT_NIL, +} + +function BuildingDialog:init(info) + self:addviews{ + widgets.Label{ + text = { + self.prompt, '\n\n', + 'Category: ', { text = self:cb_getfield('context_str'), pen = COLOR_CYAN } + }, + text_pen = COLOR_WHITE, + frame = { l = 0, t = 0 }, + }, + widgets.Label{ + view_id = 'back', + visible = false, + text = { { key = 'LEAVESCREEN', text = ': Back' } }, + frame = { r = 0, b = 0 }, + auto_width = true, + }, + widgets.FilteredList{ + view_id = 'list', + not_found_label = 'No matching buildings', + frame = { l = 0, r = 0, t = 4, b = 2 }, + icon_width = 2, + on_submit = self:callback('onSubmitItem'), + }, + widgets.Label{ + text = { { + key = 'SELECT', text = ': Select', + disabled = function() return not self.subviews.list:canSubmit() end + } }, + frame = { l = 0, b = 0 }, + } + } + self:initBuiltinMode() +end + +function BuildingDialog:getWantedFrameSize(rect) + return math.max(self.frame_width or 40, #self.prompt), math.min(28, rect.height-8) +end + +function BuildingDialog:onDestroy() + if self.on_close then + self.on_close() + end +end + +function BuildingDialog:initBuiltinMode() + local choices = {} + if not self.hide_none then + table.insert(choices, { text = self.none_caption, type_id = -1, subtype_id = -1, custom_id=-1}) + end + + if self.use_workshops then + table.insert(choices, { + icon = ARROW, text = 'workshop', key = 'CUSTOM_SHIFT_W', + cb = self:callback('initWorkshopMode') + }) + end + if self.use_furnace then + table.insert(choices, { + icon = ARROW, text = 'furnaces', key = 'CUSTOM_SHIFT_F', + cb = self:callback('initFurnaceMode') + }) + end + if self.use_trap then + table.insert(choices, { + icon = ARROW, text = 'traps', key = 'CUSTOM_SHIFT_T', + cb = self:callback('initTrapMode') + }) + end + if self.use_construction then + table.insert(choices, { + icon = ARROW, text = 'constructions', key = 'CUSTOM_SHIFT_C', + cb = self:callback('initConstructionMode') + }) + end + if self.use_custom then + table.insert(choices, { + icon = ARROW, text = 'custom workshop', key = 'CUSTOM_SHIFT_U', + cb = self:callback('initCustomMode') + }) + end + + + for i=0,df.building_type._last_item do + if (not WORKSHOP_ABSTRACT[i] or self.use_abstract)and not WORKSHOP_SPECIAL[i] then + self:addBuilding(choices, df.building_type[i], i, -1,-1,nil) + end + end + + self:pushContext('Any building', choices) +end + +function BuildingDialog:initWorkshopMode() + local choices = {} + + for i=0,df.workshop_type._last_item do + if i~=df.workshop_type.Custom and (i~=df.workshop_type.Tool or self.use_tool_workshop) then + self:addBuilding(choices, df.workshop_type[i], df.building_type.Workshop, i,-1,nil) + end + end + + self:pushContext('Workshops', choices) +end +function BuildingDialog:initTrapMode() + local choices = {} + + for i=0,df.trap_type._last_item do + self:addBuilding(choices, df.trap_type[i], df.building_type.Trap, i,-1,nil) + end + + self:pushContext('Traps', choices) +end + +function BuildingDialog:initConstructionMode() + local choices = {} + + for i=0,df.construction_type._last_item do + self:addBuilding(choices, df.construction_type[i], df.building_type.Construction, i,-1,nil) + end + + self:pushContext('Constructions', choices) +end + +function BuildingDialog:initFurnaceMode() + local choices = {} + + for i=0,df.furnace_type._last_item do + self:addBuilding(choices, df.furnace_type[i], df.building_type.Furnace, i,-1,nil) + end + + self:pushContext('Furnaces', choices) +end + +function BuildingDialog:initCustomMode() + local choices = {} + local raws=df.global.world.raws.buildings.all + for k,v in pairs(raws) do + self:addBuilding(choices, v.name, df.building_type.Workshop,df.workshop_type.Custom,v.id,v) + end + + self:pushContext('Custom workshops', choices) +end + +function BuildingDialog:addBuilding(choices, name,type_id, subtype_id, custom_id, parent) + -- Check the filter + if self.building_filter and not self.building_filter(name,type_id,subtype_id,custom_id, parent) then + return + end + + table.insert(choices, { + text = name:lower(), + customshop = parent, + type_id = type_id, subtype_id = subtype_id, custom_id=custom_id + }) +end + +function BuildingDialog:pushContext(name, choices) + if not self.back_stack then + self.back_stack = {} + self.subviews.back.visible = false + else + table.insert(self.back_stack, { + context_str = self.context_str, + all_choices = self.subviews.list:getChoices(), + edit_text = self.subviews.list:getFilter(), + selected = self.subviews.list:getSelected(), + }) + self.subviews.back.visible = true + end + + self.context_str = name + self.subviews.list:setChoices(choices, 1) +end + +function BuildingDialog:onGoBack() + local save = table.remove(self.back_stack) + self.subviews.back.visible = (#self.back_stack > 0) + + self.context_str = save.context_str + self.subviews.list:setChoices(save.all_choices) + self.subviews.list:setFilter(save.edit_text, save.selected) +end + +function BuildingDialog:submitBuilding(type_id,subtype_id,custom_id,choice,index) + self:dismiss() + + if self.on_select then + self.on_select(type_id,subtype_id,custom_id,choice,index) + end +end + +function BuildingDialog:onSubmitItem(idx, item) + if item.cb then + item:cb(idx) + else + self:submitBuilding(item.type_id, item.subtype_id,item.custom_id,item,idx) + end +end + +function BuildingDialog:onInput(keys) + if keys.LEAVESCREEN or keys.LEAVESCREEN_ALL then + if self.subviews.back.visible and not keys.LEAVESCREEN_ALL then + self:onGoBack() + else + self:dismiss() + if self.on_cancel then + self.on_cancel() + end + end + else + self:inputToSubviews(keys) + end +end + +function showBuildingPrompt(title, prompt, on_select, on_cancel, build_filter) + BuildingDialog{ + frame_title = title, + prompt = prompt, + building_filter = build_filter, + on_select = on_select, + on_cancel = on_cancel, + }:show() +end + +return _ENV diff --git a/scripts/gui/advfort.lua b/scripts/gui/advfort.lua index 4e620a405..7348e3d55 100644 --- a/scripts/gui/advfort.lua +++ b/scripts/gui/advfort.lua @@ -3,6 +3,7 @@ local gui = require 'gui' local wid=require 'gui.widgets' local dialog=require 'gui.dialogs' local buildings=require 'dfhack.buildings' +local bdialog=require 'gui.buildings' local tile_attrs = df.tiletype.attrs @@ -11,9 +12,9 @@ keybinds={ key_next={key="CUSTOM_SHIFT_T",desc="Next job in the list"}, key_prev={key="CUSTOM_SHIFT_R",desc="Previous job in the list"}, key_continue={key="A_WAIT",desc="Continue job if available"}, -key_down_alt1={key="CUSTOM_CTRL_D",desc="Use job down"},--does not work? +key_down_alt1={key="CUSTOM_CTRL_D",desc="Use job down"}, key_down_alt2={key="CURSOR_DOWN_Z_AUX",desc="Use job down"}, -key_up_alt1={key="CUSTOM_CTRL_E",desc="Use job up"}, --does not work? +key_up_alt1={key="CUSTOM_CTRL_E",desc="Use job up"}, key_up_alt2={key="CURSOR_UP_Z_AUX",desc="Use job up"}, key_use_same={key="A_MOVE_SAME_SQUARE",desc="Use job at the tile you are standing"}, } @@ -233,49 +234,15 @@ function AssignItems(items,args) end --[[ building submodule... ]]-- -function DialogBuildingChoose(on_select, on_cancel) - blist={} - for i=df.building_type._first_item,df.building_type._last_item do - table.insert(blist,df.building_type[i]) - end - dialog.showListPrompt("Building list", "Choose building:", COLOR_WHITE, blist, on_select, on_cancel, nil, true) -end -function DialogSubtypeChoose(subtype,on_select, on_cancel) - blist={} - for i=subtype._first_item,subtype._last_item do - table.insert(blist,subtype[i]) - end - dialog.showListPrompt("Subtype", "Choose subtype:", COLOR_WHITE, blist, on_select, on_cancel, nil, true) -end ---workshop, furnaces, traps -invalid_buildings={} -function SubtypeChosen(args,index) - args.subtype=index-1 - buildings.constructBuilding(args) -end -function BuildingChosen(st_pos,pos,index) - local b_type=index-2 + +function BuildingChosen(inp_args,type_id,subtype_id,custom_id) local args={} - args.type=b_type - args.pos=pos - args.items=itemsAtPos(st_pos) - if invalid_buildings[b_type] then - return - elseif b_type==df.building_type.Construction then - DialogSubtypeChoose(df.construction_type,dfhack.curry(SubtypeChosen,args)) - return - elseif b_type==df.building_type.Furnace then - DialogSubtypeChoose(df.furnace_type,dfhack.curry(SubtypeChosen,args)) - return - elseif b_type==df.building_type.Trap then - DialogSubtypeChoose(df.trap_type,dfhack.curry(SubtypeChosen,args)) - return - elseif b_type==df.building_type.Workshop then - DialogSubtypeChoose(df.workshop_type,dfhack.curry(SubtypeChosen,args)) - return - else - buildings.constructBuilding(args) - end + args.type=type_id + args.subtype=subtype_id + args.custom=custom_id + args.pos=inp_args.pos + args.items=itemsAtPos(inp_args.old_pos) + buildings.constructBuilding(args) end --[[ end of buildings ]]-- @@ -306,7 +273,7 @@ function AssignJobToBuild(args) end else - DialogBuildingChoose(dfhack.curry(BuildingChosen,args.old_pos,args.pos)) + bdialog.BuildingDialog{on_select=dfhack.curry(BuildingChosen,args),hide_none=true}:show() end end function CancelJob(unit)