From d9b4410ad5bf30abc5a2d6be76d4175c120006fc Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 19 May 2019 16:46:48 +0100 Subject: [PATCH 1/8] Added instances --- expcore/Gui/core.lua | 68 +++++----------------- expcore/Gui/instances.lua | 117 ++++++++++++++++++++++++++++++++++++++ expcore/Gui/slider.lua | 54 ++++-------------- expcore/gui.lua | 7 +++ 4 files changed, 150 insertions(+), 96 deletions(-) create mode 100644 expcore/Gui/instances.lua diff --git a/expcore/Gui/core.lua b/expcore/Gui/core.lua index 6e4e9a3e..011bf283 100644 --- a/expcore/Gui/core.lua +++ b/expcore/Gui/core.lua @@ -152,17 +152,13 @@ ]] local Gui = require 'utils.gui' local Game = require 'utils.game' -local Global = require 'utils.global' local Store = require 'expcore.store' +local Instances = require 'expcore.gui.instances' Gui._prototype = {} -- Stores the base prototype of all element defines Gui.classes = {} -- Stores the class definations used to create element defines Gui.defines = {} -- Stores the indivdual element definations Gui.names = {} -- Stores debug names to link to gui uids -Gui.instances = {} -- Stores runtime data of all active instances of an element define -Global.register(Gui.instances,function(tbl) - Gui.instances = tbl -end) --- Used internally to create new prototypes for element defines -- @tparam tbl table a table that will have functions added to it @@ -211,24 +207,18 @@ function Gui._store_factory(callback) self.store = Store.uid_location() self.categorize = categorize - Gui.instances[self.name]={} + + Instances.register(self.name,self.categorize) Store.register(self.store,function(value,category) if self.events.on_store_update then self.events.on_store_update(value,category) end - local instances = Gui.get_instances(self,category) - if instances then - - for k,element in pairs(instances) do - if element and element.valid then - callback(self,element,value) - else - instances[k] = nil - end - end - + if Instances.is_registered(self.name) then + Instances.apply_to_elements(self.name,category,function(element) + callback(self,element,value) + end) end end) @@ -256,24 +246,18 @@ function Gui._sync_store_factory(callback) self.store = location self.categorize = categorize - Gui.instances[self.name]={} + + Instances.register(self.name,self.categorize) Store.register_synced(self.store,function(value,category) if self.events.on_store_update then self.events.on_store_update(value,category) end - local instances = Gui.get_instances(self,category) - if instances then - - for k,element in pairs(instances) do - if element and element.valid then - callback(self,element,value) - else - instances[k] = nil - end - end - + if Instances.is_registered(self.name) then + Instances.apply_to_elements(self,category,function(element) + callback(self,element,value) + end) end end) @@ -380,12 +364,8 @@ function Gui._prototype:draw_to(element) new_element.enabled = self.post_authenticator(player,self.name) end - if self.store then - local category = self.categorize and self.categorize(element) or nil - local instances = Gui.get_instances(self,category) - if instances then - table.insert(instances,new_element) - end + if Instances.is_registered(self.name) then + Instances.add_element(self.name,new_element) end if self.post_draw then self.post_draw(new_element) end @@ -442,24 +422,6 @@ function Gui.get_define(name,internal) return define end ---- Gets all instances of the element define, mostly internal use and note invalid elements may be present in the return --- @tparam name string the uid or debug name for the define to get the instances for --- @tparam[opt] category string the category to get the instances for --- @treturn table a table of LuaGuiElements that might be invalid which belong to this define -function Gui.get_instances(name,category) - local define = Gui.get_define(name,true) - if not Gui.instances[define.name] then return end - - local instances = Gui.instances[define.name] - if define.categorize then - if not instances[category] then instances[category] = {} end - return instances[category] - - end - - return instances -end - --- Gets the value that is stored for a given element define, category needed if categorize function used -- @tparam name ?string|table the uid, debug name or define for the element define to get -- @tparam[opt] category string the category to get the value for diff --git a/expcore/Gui/instances.lua b/expcore/Gui/instances.lua new file mode 100644 index 00000000..72532a4b --- /dev/null +++ b/expcore/Gui/instances.lua @@ -0,0 +1,117 @@ +--- This file is a breakout from core which forcues on instance management of defines +local Global = require 'utils.global' + +local Instances = { + categorise={}, + data={} +} +Global.register(Instances.data,function(tbl) + Instances.data = tbl +end) + +function Instances.has_categories(name) + return type(Instances.categorise[name]) == 'function' +end + +function Instances.is_registered(name) + return Instances.categorise[name] ~= nil +end + +function Instances.register(name,categorise) + if _LIFECYCLE ~= _STAGE.control then + return error('Can only be called during the control stage', 2) + end + + if Instances.categorise[name] then + return error('Instances for '..name..' already exist.',2) + end + + categorise = type(categorise) == 'function' and categorise or true + + Instances.data[name] = {} + Instances.categorise[name] = categorise + + return name +end + +function Instances.add_element(name,element) + if not Instances.categorise[name] then + return error('Inavlid name for instance group: '..name,2) + end + + if Instances.has_categories(name) then + local category = Instances.categorise[name](element) + if not Instances.data[name][category] then Instances.data[name][category] = {} end + table.insert(Instances.data[name][category],element) + else + table.insert(Instances.data[name],element) + end +end + +function Instances.get_elements_raw(name,category) + if not Instances.categorise[name] then + return error('Inavlid name for instance group: '..name,2) + end + + if Instances.has_categories(name) then + return Instances.data[name][category] or {} + else + return Instances.data[name] + end +end + +function Instances.get_valid_elements(name,category,callback) + if not Instances.categorise[name] then + return error('Inavlid name for instance group: '..name,2) + end + + category = category or callback + local elements = Instances.get_elements_raw(name,category) + local categorise = Instances.has_categories(name) + + for key,element in pairs(elements) do + if not element or not element.valid then + elements[key] = nil + else + if categorise and callback then callback(element) + elseif category then category(element) end + end + end + + return elements +end +Instances.get_elements = Instances.get_valid_elements +Instances.apply_to_elements = Instances.get_valid_elements + +function Instances.unregistered_add_element(name,categorise,element) + if not Instances.data[name] then Instances.data[name] = {} end + if type(categorise) == 'function' then + local category = categorise(element) + if not Instances.data[name][category] then Instances.data[name][category] = {} end + table.insert(Instances.data[name][category],element) + else + table.insert(Instances.data[name],element) + end +end + +function Instances.unregistered_get_elements(name,category,callback) + local elements = Instances.data[name] + if category then + elements = Instances.data[name][category] + end + + if not elements then return {} end + + for key,element in pairs(elements) do + if not element or not element.valid then + elements[key] = nil + else + if callback then callback(element) end + end + end + + return elements +end +Instances.unregistered_apply_to_elements = Instances.runtime_get_elements + +return Instances \ No newline at end of file diff --git a/expcore/Gui/slider.lua b/expcore/Gui/slider.lua index adf1b2c8..eb1ba17a 100644 --- a/expcore/Gui/slider.lua +++ b/expcore/Gui/slider.lua @@ -13,47 +13,9 @@ Other functions present from expcore.gui.core ]] local Gui = require './core' +local Instances = require './instances' local Game = require 'utils.game' ---- Gets the active lables for a define --- @tparam define table the define to get the labels for --- @tparam element LuaGuiElement the element that will be used to get the category --- @treturn table the table of active instances for the slider lables -local function get_labels(define,element) - local function cat(e) - return e.player_index - end - - local name = define.name..'-label' - if not Gui.instances[name] then return end - - local categorize = define.categorize or not define.store and cat - local category = categorize and categorize(element) or nil - local instances = Gui.get_instances({ - name=name, - categorize=categorize - },category) - - return instances -end - ---- Gets and updates the label values --- @tparam define table the define to get the labels for --- @tparam element LuaGuiElement the element that will be used to get the category -local function update_lables(define,element) - local instances = get_labels(define,element) - local value = element.slider_value - if instances then - for k,instance in pairs(instances) do - if instance and instance.valid then - instance.caption = tostring(math.round(value,2)) - else - instances[k]=nil - end - end - end -end - --- Event call for on_value_changed and store update -- @tparam define table the define that this is acting on -- @tparam element LuaGuiElement the element that triggered the event @@ -69,7 +31,14 @@ local function event_call(define,element,value) define.events.on_element_update(player,element,value,percent) end - update_lables(define,element) + local category = player.name + if define.categorize then + category = define.categorize(element) + end + + Instances.unregistered_get_elements(define.name..'-label',category,function(label) + label.caption = tostring(math.round(value,2)) + end) end --- Store call for store update @@ -183,10 +152,9 @@ function Slider._prototype:draw_label(element) caption=tostring(math.round(value,2)) } - if not Gui.instances[name] then Gui.instances[name] = {} end + local categorise = self.categorise or Gui.player_store - local labels = get_labels(self,element) - table.insert(labels,new_element) + Instances.unregistered_add_element(name,categorise,new_element) return new_element end diff --git a/expcore/gui.lua b/expcore/gui.lua index 73618784..12af5c47 100644 --- a/expcore/gui.lua +++ b/expcore/gui.lua @@ -36,6 +36,13 @@ local Gui = require('./gui/core') Gui.toggle_visible(element) --- Will toggle the visiblity of an element ]] +local Instances = require('./gui/instances') +Gui.new_instance_group = Instances.registers +Gui.get_instances = Instances.get_elements +Gui.add_instance = Instances.get_elements +Gui.update_instances = Instances.apply_to_elements +Gui.classes.instances = Instances + local Button = require('./gui/buttons') Gui.new_button = Button.new_button Gui.classes.button = Button From 64c318da984d34704f226667ce45096a84242ebb Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Sun, 19 May 2019 20:45:34 +0100 Subject: [PATCH 2/8] Added comments --- expcore/Gui/instances.lua | 116 +++++++++++++++++++++++++++++++++++++- expcore/Gui/slider.lua | 3 +- 2 files changed, 115 insertions(+), 4 deletions(-) diff --git a/expcore/Gui/instances.lua b/expcore/Gui/instances.lua index 72532a4b..c1abecd0 100644 --- a/expcore/Gui/instances.lua +++ b/expcore/Gui/instances.lua @@ -1,4 +1,80 @@ --- This file is a breakout from core which forcues on instance management of defines +--[[ +>>>> Using registered instance groups + The main use of this module is to register a group of elements refered here as "instances of an element define" in which + is meant that you define the name of a group of drawn elements that are really just multiple versions of a single element. + For example this might be that you have one label in multiple places (either for one player or many) and you want to update + the caption of all of them at once; this is where this module comes it. + + First you must register the way that the intances are stored and under what name, using Instances.register you will give the + name of the collective group of instances followed by an optional categorise function which allows varients to be stored under one + name (like one for each force or player) + + -- categorise works in the same way as store categorise + -- so the function will worl here but no value is stored only gui elements + Instances.register('score',Gui.force_store) + + Then when you draw the new element to a gui you will want to add the element to the group: + + Instances.add_element('score',new_element) + + Then when you want to get the instances you have two options; Instances.get_elements or Instances.apply_to_elements when you want loop + over the elements it is more efficient to use apply_to_elements: + + Instances.get_elements('score','player') -- returns all elements that were added with the 'player' category + Instances.apply_to_elements('score','player',function(element) -- runs the function on every valid element + element.caption = 0 + end) + + Note that if you dont give a categorise function then you dont need to give a category when getting the elements. + +>>>> Using unregistered instance groups + When using a registered group and the functions that go with them it is much simpler to use and more importantly includes error checking + for valid instance group names; the down side is that the group must be registered which can only be done during startup and not during runtime. + To counter this there are two functions simlair to those above in order to add and get instances but may lead to errors not being noticed due to + the error interal error checking being skiped to allow it to work. + + The main difference between the two groups of functions is that the category must always be present even if is nil; example below shows how a + instance group would work when registered vs unregistered: + + -- Registered with category + Instances.register('score',Gui.force_store) -- force_store will return the force name of an element + Instances.add_element('score',new_element) -- the new element is added to the category based on in force + Instances.apply_to_elements('score','player',function(element) + element.caption = '0' + end) -- gets all instances from the player force and sets the caption to 0 + + -- Unregistered with category + Instances.unregistered_add_element('score','player',new_element) -- adds the new element to the player category + Instances.unregistered_apply_to_elements('score','player',function(element) + element.caption = '0' + end) -- gets all instances from the player force and sets the caption to 0 + + -- Registered without category; note that category can just be igroned + Instances.register('score') -- all instances will be under one group with no categories + Instances.add_element('score',new_element) -- adds the new element to the instance list + Instances.apply_to_elements('score',function(element) + element.caption = '0' + end) -- gets all instances and sets the element caption to 0 + + -- Unregistered without category; note that category must be given as nil + Instances.unregistered_add_element('score',nil,new_element) -- adds the new element to a single group with no categories + Instances.unregistered_apply_to_elements('score',nil,function(element) + element.caption = '0' + end) -- gets all instances and sets the element caption to 0 + +>>>> Functions + Instances.has_categories(name) --- Returns if a instnace group has a categorise function; must be registerd + Instances.is_registered(name) --- Returns if the given name is a registered instance group + Instances.register(name,categorise) --- Registers the name of an instance group to allow for storing element instances + + Instances.add_element(name,element) --- Adds an element to the instance group under the correct category; must be registered + Instances.get_elements_raw(name,category) --- Gets all element instances without first removing any invalid ones; used internally and must be registered + Instances.get_valid_elements(name,category,callback) --- Gets all valid element instances and has the option of running a callback on those that are valid + + Instances.unregistered_add_element(name,category,element) --- A version of add_element that does not require the group to be registered + Instances.unregistered_get_elements(name,category,callback) --- A version of get_elements that does not require the group to be registered +]] local Global = require 'utils.global' local Instances = { @@ -9,14 +85,26 @@ Global.register(Instances.data,function(tbl) Instances.data = tbl end) +--- Returns if a instnace group has a categorise function; must be registerd +-- @tparam name string the name of the instance group +-- @treturn boolean true if there is a categorise function function Instances.has_categories(name) return type(Instances.categorise[name]) == 'function' end +--- Returns if the given name is a registered instance group +-- @tparam name string the name of the instance group you are testing +-- @treturn boolean true if the name is registered function Instances.is_registered(name) return Instances.categorise[name] ~= nil end +--- Registers the name of an instance group to allow for storing element instances +-- @tparam name string the name of the instance group; must to unique +-- @tparam[opt] categorise function function used to turn the element into a string +-- categorise param - element LuaGuiElement - the gui element to be turned into a string +-- categorise return - string - the category that the element will be added to like the player's name or force's name +-- @treturn string the name that was added so it can be used as a varible function Instances.register(name,categorise) if _LIFECYCLE ~= _STAGE.control then return error('Can only be called during the control stage', 2) @@ -34,6 +122,9 @@ function Instances.register(name,categorise) return name end +--- Adds an element to the instance group under the correct category; must be registered +-- @tparam name string the name of the instance group to add the element to +-- @tparam element LuaGuiElement the element to add the the instance group function Instances.add_element(name,element) if not Instances.categorise[name] then return error('Inavlid name for instance group: '..name,2) @@ -48,6 +139,10 @@ function Instances.add_element(name,element) end end +--- Gets all element instances without first removing any invalid ones; used internally and must be registered +-- @tparam name string the name of the instance group to get the instances of +-- @tparam[opt] category string the category to get the instance from, not needed when no categorise function +-- @treturn table the table of element instances of which some may be invalid function Instances.get_elements_raw(name,category) if not Instances.categorise[name] then return error('Inavlid name for instance group: '..name,2) @@ -60,6 +155,12 @@ function Instances.get_elements_raw(name,category) end end +--- Gets all valid element instances and has the option of running a callback on those that are valid +-- @tparam name string the name of the instance group to get the instances of +-- @tparam[opt] category string the category to get the instances of, not needed when no categorise function +-- @tparan[opt] callback function when given the callback will be ran on all valid elements +-- callback param - element LuaGuiElement - the current valid element +-- @treturn table the table of element instances with all invalid ones removed function Instances.get_valid_elements(name,category,callback) if not Instances.categorise[name] then return error('Inavlid name for instance group: '..name,2) @@ -83,10 +184,13 @@ end Instances.get_elements = Instances.get_valid_elements Instances.apply_to_elements = Instances.get_valid_elements -function Instances.unregistered_add_element(name,categorise,element) +--- A version of add_element that does not require the group to be registered +-- @tparam name string the name of the instance group to add the element to +-- @tparam category ?string|nil the category to add the element to, can be nil but must still be given +-- @tparam element LuaGuiElement the element to add to the instance group +function Instances.unregistered_add_element(name,category,element) if not Instances.data[name] then Instances.data[name] = {} end - if type(categorise) == 'function' then - local category = categorise(element) + if category then if not Instances.data[name][category] then Instances.data[name][category] = {} end table.insert(Instances.data[name][category],element) else @@ -94,6 +198,12 @@ function Instances.unregistered_add_element(name,categorise,element) end end +--- A version of get_elements that does not require the group to be registered +-- @tparam name string the name of the instance group to get the instances of +-- @tparam category ?string|nil the category to get the instances of, can be nil but must still be given +-- @tparam[opt] callback function when given will be called on all valid instances +-- callback param - element LuaGuiElement - the current valid element +-- @treturn table the table of element instances with all invalid ones removed function Instances.unregistered_get_elements(name,category,callback) local elements = Instances.data[name] if category then diff --git a/expcore/Gui/slider.lua b/expcore/Gui/slider.lua index eb1ba17a..08895d44 100644 --- a/expcore/Gui/slider.lua +++ b/expcore/Gui/slider.lua @@ -153,8 +153,9 @@ function Slider._prototype:draw_label(element) } local categorise = self.categorise or Gui.player_store + local category = categorise(new_element) - Instances.unregistered_add_element(name,categorise,new_element) + Instances.unregistered_add_element(name,category,new_element) return new_element end From 13b34cbd602e29abc4caf75e4d29fc811053a538 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Mon, 20 May 2019 18:37:40 +0100 Subject: [PATCH 3/8] Added left frames --- expcore/Gui/left.lua | 146 ++++++++++++++++++++++++++++++++++++++++ expcore/Gui/toolbar.lua | 16 ++++- expcore/gui.lua | 30 ++++++--- 3 files changed, 178 insertions(+), 14 deletions(-) create mode 100644 expcore/Gui/left.lua diff --git a/expcore/Gui/left.lua b/expcore/Gui/left.lua new file mode 100644 index 00000000..4bca82ad --- /dev/null +++ b/expcore/Gui/left.lua @@ -0,0 +1,146 @@ +local Gui = require './core' +local Toolbar = require './toolbar' +local Buttons = require './buttons' +local mod_gui = require 'mod-gui' +local Game = require 'utils.game' +local Events = require 'utils.events' + +local LeftFrames = { + buttons={}, + draw_functions={}, + open_by_default={} +} + +function LeftFrames.get_flow(player) + return mod_gui.get_frame_flow(player) +end + +function LeftFrames.get_open(player) + local open = {} + local flow = LeftFrames.get_flow(player) + + for _,child in pairs(flow.children) do + if LeftFrames.buttons[child.name] then + if child.valid and child.visible then + table.insert(open,child) + end + end + end + + if #open == 0 then + flow[LeftFrames.toogle_button.name].visible = false + end + + return open +end + +function LeftFrames.get_frame(player,name) + local flow = LeftFrames.get_flow(player) + if flow[name] and flow[name].valid then + return flow[name] + end +end + +function LeftFrames.toogle_frame(player,name,state) + local frame = LeftFrames.get_frame(player,name) + if state ~= nil then + frame.visible = state + else + Gui.toggle_visible(frame) + end +end + +function LeftFrames.new_frame(name) + local frame_name = Gui.uid_name() + LeftFrames.add_frame(frame_name,name) + return frame_name +end + +function LeftFrames.add_frame(define_name,permision_name) + LeftFrames.buttons[define_name] = + Toolbar.new_button(permision_name) + :on_click(function(player,_element) + LeftFrames.toogle_frame(player,define_name) + end) +end + +function LeftFrames.set_open_by_default(define_name,state) + if not LeftFrames.buttons[define_name] then + return error('Left frame is not registered',2) + end + + LeftFrames.draw_functions[define_name] = state +end + +function LeftFrames.on_update(define_name,callback) + if not LeftFrames.buttons[define_name] then + return error('Left frame is not registered',2) + end + + LeftFrames.open_by_default[define_name] = callback +end + +function LeftFrames.update(define_name,player) + player = Game.get_player_from_any(player) + local frame = LeftFrames.get_frame(player,define_name) + frame.clear() + if LeftFrames.draw_functions[define_name] then + LeftFrames.draw_functions[define_name](frame,player) + end +end + +function LeftFrames.update_all_frames(player) + player = Game.get_player_from_any(player) + for define_name,draw_function in pairs(LeftFrames.draw_functions) do + local frame = LeftFrames.get_frame(player,define_name) + frame.clear() + draw_function(frame,player) + end +end + +function LeftFrames.update_all_players(define_name,update_offline) + local players = update_offline and game.players or game.connected_players + for _,player in pairs(players) do + LeftFrames.update(define_name,player) + end +end + +function LeftFrames.update_all(update_offline) + local players = update_offline and game.players or game.connected_players + for _,player in pairs(players) do + LeftFrames.update_all_frames(player) + end +end + +LeftFrames.toogle_button = +Buttons.new_button() +:set_caption('<') +:on_click(function(player,_element) + local flow = LeftFrames.get_flow(player) + + for _,child in pairs(flow.children) do + if LeftFrames.buttons[child.name] then + if child.valid and child.visible then + child.visible = false + end + end + end +end) + +Events.add(defines.events.on_player_created,function(event) + local player = Game.get_plyaer_by_index(event.player_index) + local flow = LeftFrames.get_flow(player) + + LeftFrames.toogle_button(flow) + + for define_name,_ in pairs(LeftFrames.buttons) do + local frame = flow.add{ + type='frame', + name=define_name + } + + if LeftFrames.draw_functions[define_name] then + LeftFrames.draw_functions[define_name](frame,player) + end + end +end) \ No newline at end of file diff --git a/expcore/Gui/toolbar.lua b/expcore/Gui/toolbar.lua index 44a3fafc..7f113c14 100644 --- a/expcore/Gui/toolbar.lua +++ b/expcore/Gui/toolbar.lua @@ -12,17 +12,27 @@ local Event = require 'utils.event' local Game = require 'utils.game' local Toolbar = { + permisison_names = {}, buttons = {} } +local function toolbar_allow(player,define_name) + local permisison_name = Toolbar.permisison_names[define_name] or define_name + return Roles.player_allowed(player,permisison_name) +end + +function Toolbar.permission_alias(define_name,permisison_name) + Toolbar.permisison_names[define_name] = permisison_name +end + --- Adds a new button to the toolbar -- @tparam[opt] name string the name of the button to be added -- @treturn table the button define function Toolbar.new_button(name) - name = name or #Toolbar.buttons+1 - local button = Buttons.new_button('toolbar/'..name) - button:set_post_authenticator(Roles.player_allowed) + local button = Buttons.new_button() + button:set_post_authenticator(toolbar_allow) Toolbar.add_button(button) + Toolbar.permission_alias(button.name,name) return button end diff --git a/expcore/gui.lua b/expcore/gui.lua index 12af5c47..3d02cc16 100644 --- a/expcore/gui.lua +++ b/expcore/gui.lua @@ -58,17 +58,6 @@ Gui.classes.button = Button Button._prototype:set_key_filter(filter,...) --- Adds a control key filter to the button ]] -local Toolbar = require('./gui/toolbar') -Gui.new_toolbar_button = Toolbar.new_button -Gui.add_button_to_toolbar = Toolbar.add_button -Gui.update_toolbar = Toolbar.update -Gui.classes.toolbar = Toolbar ---[[ - Toolbar.new_button(name) --- Adds a new button to the toolbar - Toolbar.add_button(button) --- Adds an existing buttton to the toolbar - Toolbar.update(player) --- Updates the player's toolbar with an new buttons or expected change in auth return -]] - local Checkbox = require('./gui/checkboxs') Gui.new_checkbox = Checkbox.new_checkbox Gui.new_radiobutton = Checkbox.new_radiobutton @@ -154,4 +143,23 @@ Gui.classes.elem_button = ElemButton ElemButton._prototype:set_default(value) --- Sets the default value for the elem button, this may be a function or a string ]] +local Toolbar = require('./gui/toolbar') +Gui.new_toolbar_button = Toolbar.new_button +Gui.add_button_to_toolbar = Toolbar.add_button +Gui.update_toolbar = Toolbar.update +Gui.classes.toolbar = Toolbar +--[[ + Toolbar.new_button(name) --- Adds a new button to the toolbar + Toolbar.add_button(button) --- Adds an existing buttton to the toolbar + Toolbar.update(player) --- Updates the player's toolbar with an new buttons or expected change in auth return +]] + +local LeftFrames = require('./gui/left') +Gui.new_left_frame = LeftFrames.new_frame +Gui.add_frame_to_left_frames = LeftFrames.add_frame +Gui.set_left_open_by_default = LeftFrames.set_open_by_default +Gui.on_left_frame_update = LeftFrames.on_update +Gui.update_left_frames = LeftFrames.update_all_frames +Gui.update_left_frame = LeftFrames.update + return Gui \ No newline at end of file From 6961614d8011d41279c3364f601279a0f3d2154a Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Mon, 20 May 2019 22:41:10 +0100 Subject: [PATCH 4/8] Added comments and fixed bugs --- expcore/Gui/buttons.lua | 2 +- expcore/Gui/checkboxs.lua | 2 +- expcore/Gui/dropdown.lua | 2 +- expcore/Gui/elem-button.lua | 2 +- expcore/Gui/left.lua | 153 +++++++++++++++++++++++++++++---- expcore/Gui/slider.lua | 4 +- expcore/Gui/test.lua | 31 ++++++- expcore/Gui/text.lua | 2 +- expcore/Gui/toolbar.lua | 20 +++-- expcore/gui.lua | 42 ++++++--- modules/commands/interface.lua | 2 +- 11 files changed, 221 insertions(+), 41 deletions(-) diff --git a/expcore/Gui/buttons.lua b/expcore/Gui/buttons.lua index bbe58e3d..46a67ec8 100644 --- a/expcore/Gui/buttons.lua +++ b/expcore/Gui/buttons.lua @@ -14,7 +14,7 @@ Other functions present from expcore.gui.core ]] local mod_gui = require 'mod-gui' -local Gui = require './core' +local Gui = require 'expcore.gui.core' local Button = { config={}, diff --git a/expcore/Gui/checkboxs.lua b/expcore/Gui/checkboxs.lua index fdc895e0..b31d9f6e 100644 --- a/expcore/Gui/checkboxs.lua +++ b/expcore/Gui/checkboxs.lua @@ -45,7 +45,7 @@ Other functions present from expcore.gui.core ]] -local Gui = require './core' +local Gui = require 'expcore.gui.core' local Store = require 'expcore.store' local Game = require 'utils.game' diff --git a/expcore/Gui/dropdown.lua b/expcore/Gui/dropdown.lua index d1c1f5e1..1737577e 100644 --- a/expcore/Gui/dropdown.lua +++ b/expcore/Gui/dropdown.lua @@ -16,7 +16,7 @@ Other functions present from expcore.gui.core ]] -local Gui = require './core' +local Gui = require 'expcore.gui.core' local Game = require 'utils.game' --- Event call for on_selection_state_changed and store update diff --git a/expcore/Gui/elem-button.lua b/expcore/Gui/elem-button.lua index eccb5082..e976d3d5 100644 --- a/expcore/Gui/elem-button.lua +++ b/expcore/Gui/elem-button.lua @@ -11,7 +11,7 @@ Other functions present from expcore.gui.core ]] -local Gui = require './core' +local Gui = require 'expcore.gui.core' local Game = require 'utils.game' --- Event call for on_elem_changed and store update diff --git a/expcore/Gui/left.lua b/expcore/Gui/left.lua index 4bca82ad..75f8fb70 100644 --- a/expcore/Gui/left.lua +++ b/expcore/Gui/left.lua @@ -1,9 +1,37 @@ -local Gui = require './core' -local Toolbar = require './toolbar' -local Buttons = require './buttons' +--- Gui structure for the toolbar (just under top left) +--[[ +>>>> Example Format + local left_gui_frame = LeftFrames.new_frame() + + LeftFrames.set_open_by_default(left_gui_frame,true) + + LeftFrames.on_update(left_gui_frame,function(frame,player) + frame.add('Hello, World!') + end) + +>>>> Functions + LeftFrames.get_flow(player) --- Gets the left frame flow for a player + LeftFrames.get_open(player) --- Gets all open frames for a player, if non are open it will remove the close all button + LeftFrames.get_frame(player,name) --- Gets one frame from the left flow by its name + LeftFrames.toggle_frame(player,name,state) --- Toggles the visiblty of a left frame, or sets its visiblty state + + LeftFrames.new_frame(name) --- Makes a new frame that can be used with on_update and adds a toggle button to the toolbar + LeftFrames.add_frame(define_name,permision_name) --- Similar to new_frame but using an already defined name (this will still add a button to the toolbar) + + LeftFrames.set_open_by_default(define_name,state) --- Sets if the frame is visible when a player joins, can also be a function to return a boolean + LeftFrames.on_update(define_name,callback) --- Registeres an update function for the gui that will be used to redraw the gui (frame is cleared before call) + LeftFrames.update(define_name,player) --- Clears the gui frame for the player and calls the update callback + + LeftFrames.update_all_frames(player) --- Clears all frames and then re-draws all frames + LeftFrames.update_all_players(define_name,update_offline) --- Clears and returns the gui frame for all players + LeftFrames.update_all(update_offline) --- Clears and updates all frames for all players +]] +local Gui = require 'expcore.gui.core' +local Toolbar = require 'expcore.gui.toolbar' +local Buttons = require 'expcore.gui.buttons' local mod_gui = require 'mod-gui' local Game = require 'utils.game' -local Events = require 'utils.events' +local Event = require 'utils.event' local LeftFrames = { buttons={}, @@ -11,10 +39,17 @@ local LeftFrames = { open_by_default={} } +--- Gets the left frame flow for a player +-- @tparam player LuaPlayer the player to get the flow of +-- @treturn LuaGuiElement the left frame flow for the player function LeftFrames.get_flow(player) + player = Game.get_player_from_any(player) return mod_gui.get_frame_flow(player) end +--- Gets all open frames for a player, if non are open it will remove the close all button +-- @tparam player LuaPlayer the player to get the flow of +-- @treturn table contains all the open (and registered) frames for the player function LeftFrames.get_open(player) local open = {} local flow = LeftFrames.get_flow(player) @@ -27,13 +62,15 @@ function LeftFrames.get_open(player) end end - if #open == 0 then - flow[LeftFrames.toogle_button.name].visible = false - end + flow[LeftFrames.toogle_button.name].visible = #open ~= 0 return open end +--- Gets one frame from the left flow by its name +-- @tparam player LuaPlayer the player to get the frame of +-- @tparam name string the name of the gui frame to get +-- @treturn LuaGuiElement the frame in the left frame flow with that name function LeftFrames.get_frame(player,name) local flow = LeftFrames.get_flow(player) if flow[name] and flow[name].valid then @@ -41,29 +78,58 @@ function LeftFrames.get_frame(player,name) end end -function LeftFrames.toogle_frame(player,name,state) +--- Toggles the visiblty of a left frame, or sets its visiblty state +-- @tparam player LuaPlayer the player to get the frame of +-- @tparam name string the name of the gui frame to toggle +-- @tparam[opt] state boolean when given will be the state that the visiblty is set to +-- @treturn boolean the new state of the visiblity +function LeftFrames.toggle_frame(player,name,state) local frame = LeftFrames.get_frame(player,name) if state ~= nil then frame.visible = state else Gui.toggle_visible(frame) end + LeftFrames.get_open(player) + return frame.visible end +--- Gets the button that was created for this left frame +-- @tparam define_name the name of the left gui frame from new_frame +-- @treturn table the define for the toggle button +function LeftFrames.get_button(define_name) + return LeftFrames.buttons[define_name] +end + +--- Makes a new frame that can be used with on_update and adds a toggle button to the toolbar +-- @tparam[opt] name string when given allows an alias to the button for the permission system +-- @treturn string the name of the left frame to be used with on_update +-- @treturn table the button define that was created function LeftFrames.new_frame(name) local frame_name = Gui.uid_name() - LeftFrames.add_frame(frame_name,name) - return frame_name + local button = LeftFrames.add_frame(frame_name,name) + return frame_name, button end +--- Similar to new_frame but using an already defined name (this will still add a button to the toolbar) +-- @tparam define_name string the name that is used to refrence this frame (like what is returned by new_frame) +-- @tparam[opt] name string when given allows an alias to the button for the permission system +-- @treturn table the button define that was created function LeftFrames.add_frame(define_name,permision_name) LeftFrames.buttons[define_name] = Toolbar.new_button(permision_name) :on_click(function(player,_element) - LeftFrames.toogle_frame(player,define_name) + LeftFrames.toggle_frame(player,define_name) end) + return LeftFrames.buttons[define_name] end +--- Sets if the frame is visible when a player joins, can also be a function to return a boolean +-- @tparam define_name the name of the left gui frame from new_frame +-- @tparam[opt=true] state ?boolean|function the default state of the visiblty, can be a function +-- state param - player LuaPlayer - the player that has joined the game +-- state param - define_name string - the define name for the frame +-- state return - boolean - false will hide the frame function LeftFrames.set_open_by_default(define_name,state) if not LeftFrames.buttons[define_name] then return error('Left frame is not registered',2) @@ -72,14 +138,35 @@ function LeftFrames.set_open_by_default(define_name,state) LeftFrames.draw_functions[define_name] = state end +--- Registeres an update function for the gui that will be used to redraw the gui (frame is cleared before call) +-- @tparam define_name the name of the left gui frame from new_frame +-- @tparam callback function the function which is called to update the gui frame +-- callback param - frame LuaGuiElement - the frame which has be cleared to have its elements redrawn +-- callback param - player LuaPlayer - the player who owns the frame function LeftFrames.on_update(define_name,callback) if not LeftFrames.buttons[define_name] then return error('Left frame is not registered',2) end - LeftFrames.open_by_default[define_name] = callback + LeftFrames.draw_functions[define_name] = callback end +--- Returns a function that can be called from a factorio event to update the frame +-- @tparam define_name string the name of the left gui frame from new_frame +-- @treturn function when this function is called it will update the frame from event.player_index +function LeftFrames.update_factory(define_name) + if not LeftFrames.draw_functions[define_name] then + return error('Left frame has no update callback',2) + end + + return function(event) + LeftFrames.update(define_name,event.player_index) + end +end + +--- Clears the gui frame for the player and calls the update callback +-- @tparam define_name the name of the left gui frame from new_frame +-- @tparam player LuaPlayer the player to update the frame for function LeftFrames.update(define_name,player) player = Game.get_player_from_any(player) local frame = LeftFrames.get_frame(player,define_name) @@ -89,6 +176,8 @@ function LeftFrames.update(define_name,player) end end +--- Clears all frames and then re-draws all frames +-- @tparam player LuaPlayer the player to update the frames for function LeftFrames.update_all_frames(player) player = Game.get_player_from_any(player) for define_name,draw_function in pairs(LeftFrames.draw_functions) do @@ -98,6 +187,9 @@ function LeftFrames.update_all_frames(player) end end +--- Clears and returns the gui frame for all players +-- @tparam define_name the name of the left gui frame from new_frame +-- @tparam[opt=false] update_offline boolean when true will also update the frame for offline players function LeftFrames.update_all_players(define_name,update_offline) local players = update_offline and game.players or game.connected_players for _,player in pairs(players) do @@ -105,6 +197,8 @@ function LeftFrames.update_all_players(define_name,update_offline) end end +--- Clears and updates all frames for all players +-- @tparam[opt=false] update_offline boolean when true will also update the frame for offline players function LeftFrames.update_all(update_offline) local players = update_offline and game.players or game.connected_players for _,player in pairs(players) do @@ -114,6 +208,7 @@ end LeftFrames.toogle_button = Buttons.new_button() +:set_tooltip('Close Windows') :set_caption('<') :on_click(function(player,_element) local flow = LeftFrames.get_flow(player) @@ -125,13 +220,22 @@ Buttons.new_button() end end end + + _element.visible = false end) -Events.add(defines.events.on_player_created,function(event) - local player = Game.get_plyaer_by_index(event.player_index) +Event.add(defines.events.on_player_created,function(event) + local player = Game.get_player_by_index(event.player_index) local flow = LeftFrames.get_flow(player) - LeftFrames.toogle_button(flow) + local style = LeftFrames.toogle_button(flow).style + style.width = 18 + style.height = 36 + style.left_padding = 0 + style.top_padding = 0 + style.right_padding = 0 + style.bottom_padding = 0 + style.font = 'default-small-bold' for define_name,_ in pairs(LeftFrames.buttons) do local frame = flow.add{ @@ -142,5 +246,22 @@ Events.add(defines.events.on_player_created,function(event) if LeftFrames.draw_functions[define_name] then LeftFrames.draw_functions[define_name](frame,player) end + + if LeftFrames.open_by_default[define_name] == false then + frame.visible = false + elseif type(LeftFrames.open_by_default[define_name]) == 'function' then + if not LeftFrames.open_by_default[define_name](player,define_name) then + frame.visible = false + end + end + + if not Toolbar.allowed(player,define_name) then + frame.visible = false + end + end -end) \ No newline at end of file + + LeftFrames.get_open(player) +end) + +return LeftFrames \ No newline at end of file diff --git a/expcore/Gui/slider.lua b/expcore/Gui/slider.lua index 08895d44..c0182369 100644 --- a/expcore/Gui/slider.lua +++ b/expcore/Gui/slider.lua @@ -12,8 +12,8 @@ Other functions present from expcore.gui.core ]] -local Gui = require './core' -local Instances = require './instances' +local Gui = require 'expcore.gui.core' +local Instances = require 'expcore.gui.instances' local Game = require 'utils.game' --- Event call for on_value_changed and store update diff --git a/expcore/Gui/test.lua b/expcore/Gui/test.lua index 459d044e..889e380c 100644 --- a/expcore/Gui/test.lua +++ b/expcore/Gui/test.lua @@ -4,7 +4,7 @@ local Gui = require 'expcore.gui' local format_chat_colour,table_keys = ext_require('expcore.common','format_chat_colour','table_keys') local Colors = require 'resources.color_presets' -local Game = require 'utils.game' +local Event = require 'utils.event' local tests = {} @@ -92,6 +92,35 @@ end) end end) +--[[ + Left Frame Test + > Left frame which holds all online player names, updates when player leaves or joins +]] + +local left_frame_name,left_gui_button = +Gui.new_left_frame('test-left-frame') + +Gui.set_left_open_by_default(left_frame_name,true) + +Gui.on_left_update(left_frame_name,function(frame,_player) + for _,player in pairs(game.connected_players) do + frame.add{ + type='label', + caption=player.name + } + end +end) + +left_gui_button +:set_caption('Test Left Gui') +:set_post_authenticator(function(player,button_name) + return global.show_test_gui +end) + +local update_left_frame = Gui.left_update_factory(left_frame_name) +Event.add(defines.events.on_player_joined_game,update_left_frame) +Event.add(defines.events.on_player_left_game,update_left_frame) + --[[ Button Tests > No display - Simple button which has no display diff --git a/expcore/Gui/text.lua b/expcore/Gui/text.lua index a56cf4d4..3a06e439 100644 --- a/expcore/Gui/text.lua +++ b/expcore/Gui/text.lua @@ -14,7 +14,7 @@ Other functions present from expcore.gui.core ]] -local Gui = require './core' +local Gui = require 'expcore.gui.core' local Game = require 'utils.game' --- Event call for on_text_changed and store update diff --git a/expcore/Gui/toolbar.lua b/expcore/Gui/toolbar.lua index 7f113c14..90fbab04 100644 --- a/expcore/Gui/toolbar.lua +++ b/expcore/Gui/toolbar.lua @@ -1,12 +1,21 @@ --- Gui structure for the toolbar (top left) --[[ +>>>> Example format + -- this is the same as any other button define, this just automatically draws it + -- you can use add_button if you already defined the button + local toolbar_button = + Toolbar.new_button('print-click') + :on_click(function(player,_element) + player.print('You clicked a button!') + end) + >>>> Functions Toolbar.new_button(name) --- Adds a new button to the toolbar Toolbar.add_button(button) --- Adds an existing buttton to the toolbar Toolbar.update(player) --- Updates the player's toolbar with an new buttons or expected change in auth return ]] -local Buttons = require './buttons' -local Gui = require './core' +local Buttons = require 'expcore.gui.buttons' +local Gui = require 'expcore.gui.core' local Roles = require 'expcore.roles' local Event = require 'utils.event' local Game = require 'utils.game' @@ -16,7 +25,7 @@ local Toolbar = { buttons = {} } -local function toolbar_allow(player,define_name) +function Toolbar.allowed(player,define_name) local permisison_name = Toolbar.permisison_names[define_name] or define_name return Roles.player_allowed(player,permisison_name) end @@ -26,11 +35,11 @@ function Toolbar.permission_alias(define_name,permisison_name) end --- Adds a new button to the toolbar --- @tparam[opt] name string the name of the button to be added +-- @tparam[opt] name string when given allows an alias to the button for the permission system -- @treturn table the button define function Toolbar.new_button(name) local button = Buttons.new_button() - button:set_post_authenticator(toolbar_allow) + button:set_post_authenticator(Toolbar.allowed) Toolbar.add_button(button) Toolbar.permission_alias(button.name,name) return button @@ -69,6 +78,7 @@ function Toolbar.update(player) element.enabled = false end end + log(table.inspect(Toolbar.buttons)) end --- When there is a new player they will have the toolbar update diff --git a/expcore/gui.lua b/expcore/gui.lua index 3d02cc16..0e68c80c 100644 --- a/expcore/gui.lua +++ b/expcore/gui.lua @@ -1,7 +1,7 @@ --- This file is used to require all the different elements of the gui module -- each module has an outline here but for more details see their seperate files in ./gui -local Gui = require('./gui/core') +local Gui = require('expcore.gui.core') --[[ Gui._prototype_factory(tbl) --- Used internally to create new prototypes for element defines Gui._event_factory(name) --- Used internally to create event handler adders for element defines @@ -36,14 +36,14 @@ local Gui = require('./gui/core') Gui.toggle_visible(element) --- Will toggle the visiblity of an element ]] -local Instances = require('./gui/instances') +local Instances = require('expcore.gui.instances') Gui.new_instance_group = Instances.registers Gui.get_instances = Instances.get_elements Gui.add_instance = Instances.get_elements Gui.update_instances = Instances.apply_to_elements Gui.classes.instances = Instances -local Button = require('./gui/buttons') +local Button = require('expcore.gui.buttons') Gui.new_button = Button.new_button Gui.classes.button = Button --[[ @@ -58,7 +58,7 @@ Gui.classes.button = Button Button._prototype:set_key_filter(filter,...) --- Adds a control key filter to the button ]] -local Checkbox = require('./gui/checkboxs') +local Checkbox = require('expcore.gui.checkboxs') Gui.new_checkbox = Checkbox.new_checkbox Gui.new_radiobutton = Checkbox.new_radiobutton Gui.new_radiobutton_option_set = Checkbox.new_option_set @@ -80,7 +80,7 @@ Gui.classes.checkbox = Checkbox Checkbox.reset_radiobutton(element,exclude,recursive) --- Sets all radiobutotn in a element to false (unless excluded) and can act recursivly ]] -local Dropdown = require('./gui/dropdown') +local Dropdown = require('expcore.gui.dropdown') Gui.new_dropdown = Dropdown.new_dropdown Gui.new_list_box = Dropdown.new_list_box Gui.classes.dropdown = Dropdown @@ -99,7 +99,7 @@ Gui.classes.dropdown = Dropdown Dropdown.get_selected_value(element) --- Returns the currently selected value rather than index ]] -local Slider = require('./gui/slider') +local Slider = require('expcore.gui.slider') Gui.new_slider = Slider.new_slider Gui.classes.slider = Slider --[[ @@ -113,7 +113,7 @@ Gui.classes.slider = Slider Slider._prototype:enable_auto_draw_label(state) --- Enables auto draw of the label, the label will share the same parent element as the slider ]] -local Text = require('./gui/text') +local Text = require('expcore.gui.text') Gui.new_text_filed = Text.new_text_field Gui.new_text_box = Text.new_text_box Gui.classes.text = Text @@ -130,7 +130,7 @@ Gui.classes.text = Text Text._prototype_box:set_read_only(state) --- Sets the text box to be read only ]] -local ElemButton = require('./gui/elem-button') +local ElemButton = require('expcore.gui.elem-button') Gui.new_elem_button = ElemButton.new_elem_button Gui.classes.elem_button = ElemButton --[[ @@ -143,7 +143,7 @@ Gui.classes.elem_button = ElemButton ElemButton._prototype:set_default(value) --- Sets the default value for the elem button, this may be a function or a string ]] -local Toolbar = require('./gui/toolbar') +local Toolbar = require('expcore.gui.toolbar') Gui.new_toolbar_button = Toolbar.new_button Gui.add_button_to_toolbar = Toolbar.add_button Gui.update_toolbar = Toolbar.update @@ -154,12 +154,32 @@ Gui.classes.toolbar = Toolbar Toolbar.update(player) --- Updates the player's toolbar with an new buttons or expected change in auth return ]] -local LeftFrames = require('./gui/left') +local LeftFrames = require('expcore.gui.left') Gui.new_left_frame = LeftFrames.new_frame Gui.add_frame_to_left_frames = LeftFrames.add_frame Gui.set_left_open_by_default = LeftFrames.set_open_by_default -Gui.on_left_frame_update = LeftFrames.on_update +Gui.on_left_update = LeftFrames.on_update +Gui.left_update_factory = LeftFrames.update_factory Gui.update_left_frames = LeftFrames.update_all_frames Gui.update_left_frame = LeftFrames.update +Gui.get_left_frame = LeftFrames.get_frame +Gui.classes.left_frames = LeftFrames +--[[ + LeftFrames.get_flow(player) --- Gets the left frame flow for a player + LeftFrames.get_open(player) --- Gets all open frames for a player, if non are open it will remove the close all button + LeftFrames.get_frame(player,name) --- Gets one frame from the left flow by its name + LeftFrames.toggle_frame(player,name,state) --- Toggles the visiblty of a left frame, or sets its visiblty state + + LeftFrames.new_frame(name) --- Makes a new frame that can be used with on_update and adds a toggle button to the toolbar + LeftFrames.add_frame(define_name,permision_name) --- Similar to new_frame but using an already defined name (this will still add a button to the toolbar) + + LeftFrames.set_open_by_default(define_name,state) --- Sets if the frame is visible when a player joins, can also be a function to return a boolean + LeftFrames.on_update(define_name,callback) --- Registeres an update function for the gui that will be used to redraw the gui (frame is cleared before call) + LeftFrames.update(define_name,player) --- Clears the gui frame for the player and calls the update callback + + LeftFrames.update_all_frames(player) --- Clears all frames and then re-draws all frames + LeftFrames.update_all_players(define_name,update_offline) --- Clears and returns the gui frame for all players + LeftFrames.update_all(update_offline) --- Clears and updates all frames for all players +]] return Gui \ No newline at end of file diff --git a/modules/commands/interface.lua b/modules/commands/interface.lua index e4ba5ec3..03604435 100644 --- a/modules/commands/interface.lua +++ b/modules/commands/interface.lua @@ -17,7 +17,7 @@ local interface_modules = { -- loads all the modules given in the above table for key,value in pairs(interface_modules) do if type(value) == 'string' then - interface_modules[key] = require(value) + interface_modules[key] = Common.opt_require(value) end end From 3a5599fcd26668f79fd59c155fdc7d496d749df8 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Tue, 21 May 2019 19:04:46 +0100 Subject: [PATCH 5/8] Refactor of left frames --- expcore/Gui/left.lua | 309 +++++++++++++++++++++------------------- expcore/Gui/test.lua | 22 ++- expcore/Gui/toolbar.lua | 1 - expcore/gui.lua | 31 ++-- 4 files changed, 189 insertions(+), 174 deletions(-) diff --git a/expcore/Gui/left.lua b/expcore/Gui/left.lua index 75f8fb70..b3d431f3 100644 --- a/expcore/Gui/left.lua +++ b/expcore/Gui/left.lua @@ -1,30 +1,48 @@ ---- Gui structure for the toolbar (just under top left) +--- Gui structure define for left frames --[[ ->>>> Example Format - local left_gui_frame = LeftFrames.new_frame() +>>>> Example formating - LeftFrames.set_open_by_default(left_gui_frame,true) - - LeftFrames.on_update(left_gui_frame,function(frame,player) - frame.add('Hello, World!') + -- first we add config that relates to the button on the toolbar, all normal button functions are present + local left_frame = + Gui.new_left_frame('test-left-frame') + :set_caption('Test Left Gui') + :set_post_authenticator(function(player,button_name) + return global.show_test_gui end) + -- then we add the config for the left frame, on_draw should draw the gui from an empty frame, on_update should take a frame from on_draw on edit it + :set_open_by_default() + :on_draw(function(_player,frame) + for _,player in pairs(game.connected_players) do + frame.add{ + type='label', + caption=player.name + } + end + end) + + -- now we can use the action factory to call events on the gui, actions are: 'update', 'update_all', 'redraw', 'redraw_all' + Event.add(defines.events.on_player_joined_game,left_frame 'update_all') + Event.add(defines.events.on_player_left_game,left_frame 'update_all') + >>>> Functions LeftFrames.get_flow(player) --- Gets the left frame flow for a player + LeftFrames.get_frame(name,player) --- Gets one frame from the left flow by its name LeftFrames.get_open(player) --- Gets all open frames for a player, if non are open it will remove the close all button - LeftFrames.get_frame(player,name) --- Gets one frame from the left flow by its name - LeftFrames.toggle_frame(player,name,state) --- Toggles the visiblty of a left frame, or sets its visiblty state + LeftFrames.toggle_frame(name,player,state) --- Toggles the visiblty of a left frame, or sets its visiblty state - LeftFrames.new_frame(name) --- Makes a new frame that can be used with on_update and adds a toggle button to the toolbar - LeftFrames.add_frame(define_name,permision_name) --- Similar to new_frame but using an already defined name (this will still add a button to the toolbar) + LeftFrames.new_frame(permision_name) --- Creates a new left frame define + LeftFrames._prototype:set_open_by_default(state) --- Sets if the frame is visible when a player joins, can also be a function to return a boolean + LeftFrames._prototype:get_frame(player) --- Gets the frame for this define from the left frame flow + LeftFrames._prototype:is_open(player) --- Returns if the player currently has this define visible + LeftFrames._prototype:toggle(player) --- Toggles the visiblty of the left frame - LeftFrames.set_open_by_default(define_name,state) --- Sets if the frame is visible when a player joins, can also be a function to return a boolean - LeftFrames.on_update(define_name,callback) --- Registeres an update function for the gui that will be used to redraw the gui (frame is cleared before call) - LeftFrames.update(define_name,player) --- Clears the gui frame for the player and calls the update callback + LeftFrames._prototype:update(player) --- Updates the contents of the left frame, first tries update callback, oter wise will clear and redraw + LeftFrames._prototype:update_all(update_offline) --- Updates the frame for all players, see update + LeftFrames._prototype:redraw(player) --- Redraws the frame by calling on_draw, will always clear the frame + LeftFrames._prototype:redraw_all(update_offline) --- Redraws the frame for all players, see redraw - LeftFrames.update_all_frames(player) --- Clears all frames and then re-draws all frames - LeftFrames.update_all_players(define_name,update_offline) --- Clears and returns the gui frame for all players - LeftFrames.update_all(update_offline) --- Clears and updates all frames for all players + LeftFrames._prototype:event_handler(action) --- Creates an event handler that will trigger one of its functions, use with Event.add ]] local Gui = require 'expcore.gui.core' local Toolbar = require 'expcore.gui.toolbar' @@ -34,10 +52,15 @@ local Game = require 'utils.game' local Event = require 'utils.event' local LeftFrames = { - buttons={}, - draw_functions={}, - open_by_default={} + frames={}, + _prototype=Gui._prototype_factory{ + on_draw = Gui._event_factory('on_draw'), + on_update = Gui._event_factory('on_update') + } } +setmetatable(LeftFrames._prototype, { + __index = Buttons._prototype +}) --- Gets the left frame flow for a player -- @tparam player LuaPlayer the player to get the flow of @@ -47,6 +70,18 @@ function LeftFrames.get_flow(player) return mod_gui.get_frame_flow(player) end +--- Gets one frame from the left flow by its name +-- @tparam name string the name of the gui frame to get +-- @tparam player LuaPlayer the player to get the frame of +-- @treturn LuaGuiElement the frame in the left frame flow with that name +function LeftFrames.get_frame(name,player) + local define = LeftFrames.frames[name] + if not define then + return error('Left Frame '..name..' is not defined.',2) + end + return define:get_frame(player) +end + --- Gets all open frames for a player, if non are open it will remove the close all button -- @tparam player LuaPlayer the player to get the flow of -- @treturn table contains all the open (and registered) frames for the player @@ -54,181 +89,169 @@ function LeftFrames.get_open(player) local open = {} local flow = LeftFrames.get_flow(player) - for _,child in pairs(flow.children) do - if LeftFrames.buttons[child.name] then - if child.valid and child.visible then - table.insert(open,child) - end + for _,define in pairs(LeftFrames.frames) do + if define:is_open(player) then + table.insert(open,define) end end - flow[LeftFrames.toogle_button.name].visible = #open ~= 0 + flow[LeftFrames.toggle_button.name].visible = #open ~= 0 return open end ---- Gets one frame from the left flow by its name --- @tparam player LuaPlayer the player to get the frame of --- @tparam name string the name of the gui frame to get --- @treturn LuaGuiElement the frame in the left frame flow with that name -function LeftFrames.get_frame(player,name) - local flow = LeftFrames.get_flow(player) - if flow[name] and flow[name].valid then - return flow[name] - end -end - --- Toggles the visiblty of a left frame, or sets its visiblty state --- @tparam player LuaPlayer the player to get the frame of -- @tparam name string the name of the gui frame to toggle +-- @tparam player LuaPlayer the player to get the frame of -- @tparam[opt] state boolean when given will be the state that the visiblty is set to -- @treturn boolean the new state of the visiblity -function LeftFrames.toggle_frame(player,name,state) - local frame = LeftFrames.get_frame(player,name) +function LeftFrames.toggle_frame(name,player,state) + local define = LeftFrames.frames[name] + if not define then + return error('Left Frame '..name..' is not defined.',2) + end + + local frame = LeftFrames.get_frame(name,player) if state ~= nil then frame.visible = state else Gui.toggle_visible(frame) end + LeftFrames.get_open(player) + return frame.visible end ---- Gets the button that was created for this left frame --- @tparam define_name the name of the left gui frame from new_frame --- @treturn table the define for the toggle button -function LeftFrames.get_button(define_name) - return LeftFrames.buttons[define_name] -end +--- Creates a new left frame define +-- @tparam permision_name string the name that can be used with the permision system +-- @treturn table the new left frame define +function LeftFrames.new_frame(permision_name) ---- Makes a new frame that can be used with on_update and adds a toggle button to the toolbar --- @tparam[opt] name string when given allows an alias to the button for the permission system --- @treturn string the name of the left frame to be used with on_update --- @treturn table the button define that was created -function LeftFrames.new_frame(name) - local frame_name = Gui.uid_name() - local button = LeftFrames.add_frame(frame_name,name) - return frame_name, button -end + local self = Toolbar.new_button(permision_name) ---- Similar to new_frame but using an already defined name (this will still add a button to the toolbar) --- @tparam define_name string the name that is used to refrence this frame (like what is returned by new_frame) --- @tparam[opt] name string when given allows an alias to the button for the permission system --- @treturn table the button define that was created -function LeftFrames.add_frame(define_name,permision_name) - LeftFrames.buttons[define_name] = - Toolbar.new_button(permision_name) - :on_click(function(player,_element) - LeftFrames.toggle_frame(player,define_name) + local mt = getmetatable(self) + mt.__index = LeftFrames._prototype + mt.__call = self.event_handler + + self:on_click(function(player,_element) + self:toggle(player) end) - return LeftFrames.buttons[define_name] + + LeftFrames.frames[self.name] = self + + return self end --- Sets if the frame is visible when a player joins, can also be a function to return a boolean --- @tparam define_name the name of the left gui frame from new_frame -- @tparam[opt=true] state ?boolean|function the default state of the visiblty, can be a function -- state param - player LuaPlayer - the player that has joined the game -- state param - define_name string - the define name for the frame -- state return - boolean - false will hide the frame -function LeftFrames.set_open_by_default(define_name,state) - if not LeftFrames.buttons[define_name] then - return error('Left frame is not registered',2) +function LeftFrames._prototype:set_open_by_default(state) + if state == false then + self.open_by_default = false + else + self.open_by_default = state end - - LeftFrames.draw_functions[define_name] = state + return self end ---- Registeres an update function for the gui that will be used to redraw the gui (frame is cleared before call) --- @tparam define_name the name of the left gui frame from new_frame --- @tparam callback function the function which is called to update the gui frame --- callback param - frame LuaGuiElement - the frame which has be cleared to have its elements redrawn --- callback param - player LuaPlayer - the player who owns the frame -function LeftFrames.on_update(define_name,callback) - if not LeftFrames.buttons[define_name] then - return error('Left frame is not registered',2) - end - - LeftFrames.draw_functions[define_name] = callback -end - ---- Returns a function that can be called from a factorio event to update the frame --- @tparam define_name string the name of the left gui frame from new_frame --- @treturn function when this function is called it will update the frame from event.player_index -function LeftFrames.update_factory(define_name) - if not LeftFrames.draw_functions[define_name] then - return error('Left frame has no update callback',2) - end - - return function(event) - LeftFrames.update(define_name,event.player_index) +--- Gets the frame for this define from the left frame flow +-- @tparam player LuaPlayer the player to get the frame of +-- @treturn LuaGuiElement the frame in the left frame flow for this define +function LeftFrames._prototype:get_frame(player) + local flow = LeftFrames.get_flow(player) + if flow[self.name] and flow[self.name].valid then + return flow[self.name] end end ---- Clears the gui frame for the player and calls the update callback --- @tparam define_name the name of the left gui frame from new_frame --- @tparam player LuaPlayer the player to update the frame for -function LeftFrames.update(define_name,player) - player = Game.get_player_from_any(player) - local frame = LeftFrames.get_frame(player,define_name) - frame.clear() - if LeftFrames.draw_functions[define_name] then - LeftFrames.draw_functions[define_name](frame,player) - end +--- Returns if the player currently has this define visible +-- @tparam player LuaPlayer the player to get the frame of +-- @treturn boolean true if it is open/visible +function LeftFrames._prototype:is_open(player) + local frame = self:get_frame(player) + return frame and frame.visible or false end ---- Clears all frames and then re-draws all frames --- @tparam player LuaPlayer the player to update the frames for -function LeftFrames.update_all_frames(player) - player = Game.get_player_from_any(player) - for define_name,draw_function in pairs(LeftFrames.draw_functions) do - local frame = LeftFrames.get_frame(player,define_name) +--- Toggles the visiblty of the left frame +-- @tparam player LuaPlayer the player to toggle the frame of +-- @treturn boolean the new state of the visiblity +function LeftFrames._prototype:toggle(player) + local frame = self:get_frame(player) + Gui.toggle_visible(frame) + LeftFrames.get_open(player) + return frame.visible +end + +--- Updates the contents of the left frame, first tries update callback, oter wise will clear and redraw +-- @tparam player LuaPlayer the player to update the frame of +function LeftFrames._prototype:update(player) + local frame = self:get_frame(player) + if self.events.on_update then + self.events.on_update(player,frame) + elseif self.events.on_draw then frame.clear() - draw_function(frame,player) + self.events.on_draw(player,frame) end end ---- Clears and returns the gui frame for all players --- @tparam define_name the name of the left gui frame from new_frame --- @tparam[opt=false] update_offline boolean when true will also update the frame for offline players -function LeftFrames.update_all_players(define_name,update_offline) - local players = update_offline and game.players or game.connected_players +--- Updates the frame for all players, see update +-- @tparam[opt=false] update_offline boolean when true will update the frame for offline players +function LeftFrames._prototype:update_all(update_offline) + local players = update_offline == true and game.players or game.connected_players for _,player in pairs(players) do - LeftFrames.update(define_name,player) + self:update(player) end end ---- Clears and updates all frames for all players --- @tparam[opt=false] update_offline boolean when true will also update the frame for offline players -function LeftFrames.update_all(update_offline) - local players = update_offline and game.players or game.connected_players +--- Redraws the frame by calling on_draw, will always clear the frame +-- @tparam player LuaPlayer the player to update the frame of +function LeftFrames._prototype:redraw(player) + local frame = self:get_frame(player) + frame.claer() + if self.events.on_draw then + self.events.on_draw(player,frame) + end +end + +--- Redraws the frame for all players, see redraw +-- @tparam[opt=false] update_offline boolean when true will update the frame for offline players +function LeftFrames._prototype:redraw_all(update_offline) + local players = update_offline == true and game.players or game.connected_players for _,player in pairs(players) do - LeftFrames.update_all_frames(player) + self:redraw(player) end end -LeftFrames.toogle_button = +--- Creates an event handler that will trigger one of its functions, use with Event.add +-- @tparam[opt=update] action string the action to take on this event +function LeftFrames._prototype:event_handler(action) + action = action or 'update' + return function(event) + local player = Game.get_player_by_index(event.player_index) + self[action](self,player) + end +end + +LeftFrames.toggle_button = Buttons.new_button() :set_tooltip('Close Windows') :set_caption('<') -:on_click(function(player,_element) - local flow = LeftFrames.get_flow(player) - - for _,child in pairs(flow.children) do - if LeftFrames.buttons[child.name] then - if child.valid and child.visible then - child.visible = false - end - end +:on_click(function(player,element) + for _,define in pairs(LeftFrames.frames) do + local frame = LeftFrames.get_frame(define.name,player) + frame.visible = false end - - _element.visible = false + element.visible = false end) Event.add(defines.events.on_player_created,function(event) local player = Game.get_player_by_index(event.player_index) local flow = LeftFrames.get_flow(player) - local style = LeftFrames.toogle_button(flow).style + local style = LeftFrames.toggle_button(flow).style style.width = 18 style.height = 36 style.left_padding = 0 @@ -237,25 +260,25 @@ Event.add(defines.events.on_player_created,function(event) style.bottom_padding = 0 style.font = 'default-small-bold' - for define_name,_ in pairs(LeftFrames.buttons) do + for _,define in pairs(LeftFrames.frames) do local frame = flow.add{ type='frame', - name=define_name + name=define.name } - if LeftFrames.draw_functions[define_name] then - LeftFrames.draw_functions[define_name](frame,player) + if define.events.on_draw then + define.events.on_draw(player,frame) end - if LeftFrames.open_by_default[define_name] == false then + if define.open_by_default == false then frame.visible = false - elseif type(LeftFrames.open_by_default[define_name]) == 'function' then - if not LeftFrames.open_by_default[define_name](player,define_name) then + elseif type(define.open_by_default) == 'function' then + if not define.open_by_default(player,define.name) then frame.visible = false end end - if not Toolbar.allowed(player,define_name) then + if not Toolbar.allowed(player,define.name) then frame.visible = false end diff --git a/expcore/Gui/test.lua b/expcore/Gui/test.lua index 889e380c..3a1a013c 100644 --- a/expcore/Gui/test.lua +++ b/expcore/Gui/test.lua @@ -97,12 +97,15 @@ end) > Left frame which holds all online player names, updates when player leaves or joins ]] -local left_frame_name,left_gui_button = +local left_frame = Gui.new_left_frame('test-left-frame') +:set_caption('Test Left Gui') +:set_post_authenticator(function(player,button_name) + return global.show_test_gui +end) -Gui.set_left_open_by_default(left_frame_name,true) - -Gui.on_left_update(left_frame_name,function(frame,_player) +:set_open_by_default() +:on_draw(function(_player,frame) for _,player in pairs(game.connected_players) do frame.add{ type='label', @@ -111,15 +114,8 @@ Gui.on_left_update(left_frame_name,function(frame,_player) end end) -left_gui_button -:set_caption('Test Left Gui') -:set_post_authenticator(function(player,button_name) - return global.show_test_gui -end) - -local update_left_frame = Gui.left_update_factory(left_frame_name) -Event.add(defines.events.on_player_joined_game,update_left_frame) -Event.add(defines.events.on_player_left_game,update_left_frame) +Event.add(defines.events.on_player_joined_game,left_frame 'update_all') +Event.add(defines.events.on_player_left_game,left_frame 'update_all') --[[ Button Tests diff --git a/expcore/Gui/toolbar.lua b/expcore/Gui/toolbar.lua index 90fbab04..87843f5a 100644 --- a/expcore/Gui/toolbar.lua +++ b/expcore/Gui/toolbar.lua @@ -78,7 +78,6 @@ function Toolbar.update(player) element.enabled = false end end - log(table.inspect(Toolbar.buttons)) end --- When there is a new player they will have the toolbar update diff --git a/expcore/gui.lua b/expcore/gui.lua index 0e68c80c..321c1def 100644 --- a/expcore/gui.lua +++ b/expcore/gui.lua @@ -155,31 +155,28 @@ Gui.classes.toolbar = Toolbar ]] local LeftFrames = require('expcore.gui.left') +Gui.get_left_frame_flow = LeftFrames.get_flow +Gui.toggle_left_frame = LeftFrames.toggle_frame Gui.new_left_frame = LeftFrames.new_frame -Gui.add_frame_to_left_frames = LeftFrames.add_frame -Gui.set_left_open_by_default = LeftFrames.set_open_by_default -Gui.on_left_update = LeftFrames.on_update -Gui.left_update_factory = LeftFrames.update_factory -Gui.update_left_frames = LeftFrames.update_all_frames -Gui.update_left_frame = LeftFrames.update -Gui.get_left_frame = LeftFrames.get_frame Gui.classes.left_frames = LeftFrames --[[ LeftFrames.get_flow(player) --- Gets the left frame flow for a player + LeftFrames.get_frame(name,player) --- Gets one frame from the left flow by its name LeftFrames.get_open(player) --- Gets all open frames for a player, if non are open it will remove the close all button - LeftFrames.get_frame(player,name) --- Gets one frame from the left flow by its name - LeftFrames.toggle_frame(player,name,state) --- Toggles the visiblty of a left frame, or sets its visiblty state + LeftFrames.toggle_frame(name,player,state) --- Toggles the visiblty of a left frame, or sets its visiblty state - LeftFrames.new_frame(name) --- Makes a new frame that can be used with on_update and adds a toggle button to the toolbar - LeftFrames.add_frame(define_name,permision_name) --- Similar to new_frame but using an already defined name (this will still add a button to the toolbar) + LeftFrames.new_frame(permision_name) --- Creates a new left frame define + LeftFrames._prototype:set_open_by_default(state) --- Sets if the frame is visible when a player joins, can also be a function to return a boolean + LeftFrames._prototype:get_frame(player) --- Gets the frame for this define from the left frame flow + LeftFrames._prototype:is_open(player) --- Returns if the player currently has this define visible + LeftFrames._prototype:toggle(player) --- Toggles the visiblty of the left frame - LeftFrames.set_open_by_default(define_name,state) --- Sets if the frame is visible when a player joins, can also be a function to return a boolean - LeftFrames.on_update(define_name,callback) --- Registeres an update function for the gui that will be used to redraw the gui (frame is cleared before call) - LeftFrames.update(define_name,player) --- Clears the gui frame for the player and calls the update callback + LeftFrames._prototype:update(player) --- Updates the contents of the left frame, first tries update callback, oter wise will clear and redraw + LeftFrames._prototype:update_all(update_offline) --- Updates the frame for all players, see update + LeftFrames._prototype:redraw(player) --- Redraws the frame by calling on_draw, will always clear the frame + LeftFrames._prototype:redraw_all(update_offline) --- Redraws the frame for all players, see redraw - LeftFrames.update_all_frames(player) --- Clears all frames and then re-draws all frames - LeftFrames.update_all_players(define_name,update_offline) --- Clears and returns the gui frame for all players - LeftFrames.update_all(update_offline) --- Clears and updates all frames for all players + LeftFrames._prototype:event_handler(action) --- Creates an event handler that will trigger one of its functions, use with Event.add ]] return Gui \ No newline at end of file From 37cc34b3925f81d7e2b07d4ce2b22c2b43c2ff72 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Thu, 23 May 2019 19:17:29 +0100 Subject: [PATCH 6/8] Added center frame --- expcore/Gui/center.lua | 190 +++++++++++++++++++++++++++++++++++++++++ expcore/Gui/core.lua | 2 +- expcore/Gui/test.lua | 18 ++-- expcore/gui.lua | 42 ++++++--- 4 files changed, 231 insertions(+), 21 deletions(-) create mode 100644 expcore/Gui/center.lua diff --git a/expcore/Gui/center.lua b/expcore/Gui/center.lua new file mode 100644 index 00000000..9e836409 --- /dev/null +++ b/expcore/Gui/center.lua @@ -0,0 +1,190 @@ +--- Gui structure define for center gui frames +--[[ +>>>> Functions + CenterFrames.get_flow(player) --- Gets the center flow for a player + CenterFrames.clear_flow(player) --- Clears the center flow for a player + CenterFrames.draw_frame(player,name) --- Draws the center frame for a player, if already open then will do nothing + CenterFrames.redraw_frame(player,name) --- Draws the center frame for a player, if already open then will destroy it and redraw + CenterFrames.toggle_frame(player,name,state) --- Toggles if the frame is currently open or not, will open if closed and close if open + + CenterFrames.new_frame(permision_name) --- Sets the frame to be the current active gui when opened and closes all other frames + CenterFrames._prototype:set_auto_focus(state) --- Sets the frame to be the current active gui when opened and closes all other frames + CenterFrames._prototype:draw_frame(player) --- Draws this frame to the player, if already open does nothing (will call on_draw to draw to the frame) + CenterFrames._prototype:redraw_frame(player) --- Draws this frame to the player, if already open it will remove it and redraw it (will call on_draw to draw to the frame) + CenterFrames._prototype:toggle_frame(player) --- Toggles if the frame is open, if open it will close it and if closed it will open it + CenterFrames._prototype:event_handler(action) --- Creates an event handler that will trigger one of its functions, use with Event.add +]] +local Gui = require 'expcore.gui.core' +local Toolbar = require 'expcore.gui.toolbar' +local Game = require 'utils.game' + +local CenterFrames = { + _prototype = Gui._prototype_factory{ + on_draw = Gui._event_factory('on_draw') + } +} + +--- Gets the center flow for a player +-- @tparam player LuapPlayer the player to get the flow for +-- @treturn LuaGuiElement the center flow +function CenterFrames.get_flow(player) + player = Game.get_player_from_any(player) + return player.gui.center +end + +--- Clears the center flow for a player +-- @tparam player LuapPlayer the player to clear the flow for +function CenterFrames.clear_flow(player) + local flow = CenterFrames.get_flow(player) + flow.clear() +end + +--- Draws the center frame for a player, if already open then will do nothing +-- @tparam player LuapPlayer the player that will have the frame drawn +-- @tparam name string the name of the hui that will drawn +-- @treturn LuaGuiElement the new frame that was made +function CenterFrames.draw_frame(player,name) + local define = Gui.get_define(name,true) + if define then + return define:draw_frame(player) + end +end + +--- Draws the center frame for a player, if already open then will destroy it and redraw +-- @tparam player LuapPlayer the player that will have the frame drawn +-- @tparam name string the name of the hui that will drawn +-- @treturn LuaGuiElement the new frame that was made +function CenterFrames.redraw_frame(player,name) + local define = Gui.get_define(name,true) + if define then + return define:draw_frame(player) + end +end + +--- Toggles if the frame is currently open or not, will open if closed and close if open +-- @tparam player LuapPlayer the player that will have the frame toggled +-- @tparam name string the name of the hui that will be toggled +-- @tparam[opt] state boolean when set will force a state for the frame +-- @treturn boolean if the frame if no open or closed +function CenterFrames.toggle_frame(player,name,state) + local define = Gui.get_define(name,true) + if define then + if state == true then + define:draw_frame(player) + return true + elseif state == false then + local flow = CenterFrames.get_flow(player) + if flow[define.name] then + flow[define.name].destroy() + end + return false + else + return define:toggle_frame(player) + end + end +end + +--- Creates a new center frame define +-- @tparam permision_name string the name that can be used with the permision system +-- @treturn table the new center frame define +function CenterFrames.new_frame(permision_name) + local self = Toolbar.new_button(permision_name) + + self:on_click(function(player,element) + self:toggle_frame(player) + end) + + local mt = getmetatable(self) + mt.__index = CenterFrames._prototype + mt.__call = self.event_handler + + Gui.on_custom_close(self.name,function(event) + local element = event.element + if element and element.valid then element.destroy() end + end) + + return self +end + +--- Sets the frame to be the current active gui when opened and closes all other frames +-- @tparam[opt=true] state boolean when true will auto close other frames and set this frame as player.opened +function CenterFrames._prototype:set_auto_focus(state) + if state == false then + self.auto_focus = false + else + self.auto_focus = true + end +end + +--- Draws this frame to the player, if already open does nothing (will call on_draw to draw to the frame) +-- @tparam player LuaPlayer the player to draw the frame for +-- @treturn LuaGuiElement the new frame that was drawn +function CenterFrames._prototype:draw_frame(player) + player = Game.get_player_from_any(player) + local flow = CenterFrames.get_flow(player) + + if flow[self.name] then + return flow[self.name] + end + + if self.auto_focus then + flow.clear() + end + + local frame = flow.add{ + type='frame', + name=self.name + } + + if self.auto_focus then + player.opened = frame + end + + if self.events.on_draw then + self.events.on_draw(player,frame) + end + + return frame +end + +--- Draws this frame to the player, if already open it will remove it and redraw it (will call on_draw to draw to the frame) +-- @tparam player LuaPlayer the player to draw the frame for +-- @treturn LuaGuiElement the new frame that was drawn +function CenterFrames._prototype:redraw_frame(player) + player = Game.get_player_from_any(player) + local flow = CenterFrames.get_flow(player) + + if flow[self.name] then + flow[self.name].destroy() + end + + return self:draw_frame(player) +end + +--- Toggles if the frame is open, if open it will close it and if closed it will open it +-- @tparam player LuaPlayer the player to draw the frame for +-- @treturn boolean with the gui frame is now open +function CenterFrames._prototype:toggle_frame(player) + player = Game.get_player_from_any(player) + local flow = CenterFrames.get_flow(player) + + if flow[self.name] then + flow[self.name].destroy() + return false + else + self:draw_frame(player) + return true + end +end + +--- Creates an event handler that will trigger one of its functions, use with Event.add +-- @tparam[opt=update] action string the action to take on this event +function CenterFrames._prototype:event_handler(action) + action = action or 'update' + return function(event) + local player = Game.get_player_by_index(event.player_index) + self[action](self,player) + end +end + +return CenterFrames \ No newline at end of file diff --git a/expcore/Gui/core.lua b/expcore/Gui/core.lua index 011bf283..16c9fe5a 100644 --- a/expcore/Gui/core.lua +++ b/expcore/Gui/core.lua @@ -415,7 +415,7 @@ function Gui.get_define(name,internal) return Gui.defines[Gui.names[name]] elseif not define then - return error('Invalid name for checkbox, name not found.',internal and 3 or 2) or nil + return error('Invalid name for element define, name not found.',internal and 3 or 2) or nil end diff --git a/expcore/Gui/test.lua b/expcore/Gui/test.lua index 3a1a013c..31b289f2 100644 --- a/expcore/Gui/test.lua +++ b/expcore/Gui/test.lua @@ -13,7 +13,6 @@ local tests = {} > No display - Toolbar button with no display > With caption - Toolbar button with a caption display > With icons - Toolbar button with an icon - > Main test gui - Main test gui triggers all other tests ]] Gui.new_toolbar_button('click-1') @@ -42,20 +41,19 @@ end) player.print('CLICK 3') end) -Gui.new_toolbar_button('gui-test-open') +--[[ + Center Frame Tests + > Main test gui - Main test gui triggers all other tests +]] + +local test_gui = +Gui.new_center_frame('gui-test-open') :set_caption('Open Test Gui') :set_post_authenticator(function(player,button_name) return global.show_test_gui end) -:on_click(function(player,_element) - if player.gui.center.TestGui then player.gui.center.TestGui.destroy() return end - - local frame = player.gui.center.add{ - type='frame', - caption='Gui Test', - name='TestGui' - } +:on_draw(function(player,frame) for test_group_name,test_group in pairs(tests) do player.print('Starting tests for: '..format_chat_colour(test_group_name,Colors.cyan)) diff --git a/expcore/gui.lua b/expcore/gui.lua index 321c1def..6568e744 100644 --- a/expcore/gui.lua +++ b/expcore/gui.lua @@ -1,7 +1,7 @@ --- This file is used to require all the different elements of the gui module -- each module has an outline here but for more details see their seperate files in ./gui -local Gui = require('expcore.gui.core') +local Gui = require 'expcore.gui.core' --[[ Gui._prototype_factory(tbl) --- Used internally to create new prototypes for element defines Gui._event_factory(name) --- Used internally to create event handler adders for element defines @@ -36,14 +36,14 @@ local Gui = require('expcore.gui.core') Gui.toggle_visible(element) --- Will toggle the visiblity of an element ]] -local Instances = require('expcore.gui.instances') +local Instances = require 'expcore.gui.instances' Gui.new_instance_group = Instances.registers Gui.get_instances = Instances.get_elements Gui.add_instance = Instances.get_elements Gui.update_instances = Instances.apply_to_elements Gui.classes.instances = Instances -local Button = require('expcore.gui.buttons') +local Button = require 'expcore.gui.buttons' Gui.new_button = Button.new_button Gui.classes.button = Button --[[ @@ -58,7 +58,7 @@ Gui.classes.button = Button Button._prototype:set_key_filter(filter,...) --- Adds a control key filter to the button ]] -local Checkbox = require('expcore.gui.checkboxs') +local Checkbox = require 'expcore.gui.checkboxs' Gui.new_checkbox = Checkbox.new_checkbox Gui.new_radiobutton = Checkbox.new_radiobutton Gui.new_radiobutton_option_set = Checkbox.new_option_set @@ -80,7 +80,7 @@ Gui.classes.checkbox = Checkbox Checkbox.reset_radiobutton(element,exclude,recursive) --- Sets all radiobutotn in a element to false (unless excluded) and can act recursivly ]] -local Dropdown = require('expcore.gui.dropdown') +local Dropdown = require 'expcore.gui.dropdown' Gui.new_dropdown = Dropdown.new_dropdown Gui.new_list_box = Dropdown.new_list_box Gui.classes.dropdown = Dropdown @@ -99,7 +99,7 @@ Gui.classes.dropdown = Dropdown Dropdown.get_selected_value(element) --- Returns the currently selected value rather than index ]] -local Slider = require('expcore.gui.slider') +local Slider = require 'expcore.gui.slider' Gui.new_slider = Slider.new_slider Gui.classes.slider = Slider --[[ @@ -113,7 +113,7 @@ Gui.classes.slider = Slider Slider._prototype:enable_auto_draw_label(state) --- Enables auto draw of the label, the label will share the same parent element as the slider ]] -local Text = require('expcore.gui.text') +local Text = require 'expcore.gui.text' Gui.new_text_filed = Text.new_text_field Gui.new_text_box = Text.new_text_box Gui.classes.text = Text @@ -130,7 +130,7 @@ Gui.classes.text = Text Text._prototype_box:set_read_only(state) --- Sets the text box to be read only ]] -local ElemButton = require('expcore.gui.elem-button') +local ElemButton = require 'expcore.gui.elem-button' Gui.new_elem_button = ElemButton.new_elem_button Gui.classes.elem_button = ElemButton --[[ @@ -143,7 +143,7 @@ Gui.classes.elem_button = ElemButton ElemButton._prototype:set_default(value) --- Sets the default value for the elem button, this may be a function or a string ]] -local Toolbar = require('expcore.gui.toolbar') +local Toolbar = require 'expcore.gui.toolbar' Gui.new_toolbar_button = Toolbar.new_button Gui.add_button_to_toolbar = Toolbar.add_button Gui.update_toolbar = Toolbar.update @@ -154,7 +154,7 @@ Gui.classes.toolbar = Toolbar Toolbar.update(player) --- Updates the player's toolbar with an new buttons or expected change in auth return ]] -local LeftFrames = require('expcore.gui.left') +local LeftFrames = require 'expcore.gui.left' Gui.get_left_frame_flow = LeftFrames.get_flow Gui.toggle_left_frame = LeftFrames.toggle_frame Gui.new_left_frame = LeftFrames.new_frame @@ -179,4 +179,26 @@ Gui.classes.left_frames = LeftFrames LeftFrames._prototype:event_handler(action) --- Creates an event handler that will trigger one of its functions, use with Event.add ]] +local CenterFrames = require 'expcore.gui.center' +Gui.get_center_flow = CenterFrames.get_flow +Gui.toggle_left_frame = CenterFrames.toggle_frame +Gui.draw_center_frame = CenterFrames.draw_frame +Gui.redraw_center_frame = CenterFrames.redraw_frames +Gui.new_center_frame = CenterFrames.new_frame +Gui.classes.center_frames = CenterFrames +--[[ + CenterFrames.get_flow(player) --- Gets the center flow for a player + CenterFrames.clear_flow(player) --- Clears the center flow for a player + CenterFrames.draw_frame(player,name) --- Draws the center frame for a player, if already open then will do nothing + CenterFrames.redraw_frame(player,name) --- Draws the center frame for a player, if already open then will destory it and redraw + CenterFrames.toggle_frame(player,name,state) --- Toggles if the frame is currently open or not, will open if closed and close if open + + CenterFrames.new_frame(permision_name) --- Sets the frame to be the current active gui when opened and closes all other frames + CenterFrames._prototype:set_auto_focus(state) --- Sets the frame to be the current active gui when opened and closes all other frames + CenterFrames._prototype:draw_frame(player) --- Draws this frame to the player, if already open does nothing (will call on_draw to draw to the frame) + CenterFrames._prototype:redraw_frame(player) --- Draws this frame to the player, if already open it will remove it and redraw it (will call on_draw to draw to the frame) + CenterFrames._prototype:toggle_frame(player) --- Toggles if the frame is open, if open it will close it and if closed it will open it + CenterFrames._prototype:event_handler(action) --- Creates an event handler that will trigger one of its functions, use with Event.add +]] + return Gui \ No newline at end of file From bda4750871c709abcd18621494fe4ece23d0228f Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Thu, 23 May 2019 22:13:07 +0100 Subject: [PATCH 7/8] Added progress bar --- expcore/Gui/buttons.lua | 1 - expcore/Gui/center.lua | 1 + expcore/Gui/left.lua | 2 + expcore/Gui/progress-bar.lua | 336 +++++++++++++++++++++++++++++++++++ expcore/Gui/test.lua | 48 +++++ expcore/gui.lua | 26 +++ 6 files changed, 413 insertions(+), 1 deletion(-) create mode 100644 expcore/Gui/progress-bar.lua diff --git a/expcore/Gui/buttons.lua b/expcore/Gui/buttons.lua index 46a67ec8..9e3ae887 100644 --- a/expcore/Gui/buttons.lua +++ b/expcore/Gui/buttons.lua @@ -17,7 +17,6 @@ local mod_gui = require 'mod-gui' local Gui = require 'expcore.gui.core' local Button = { - config={}, _prototype=Gui._prototype_factory{ on_click = Gui._event_factory('on_click'), on_left_click = Gui._event_factory('on_left_click'), diff --git a/expcore/Gui/center.lua b/expcore/Gui/center.lua index 9e836409..b849075a 100644 --- a/expcore/Gui/center.lua +++ b/expcore/Gui/center.lua @@ -8,6 +8,7 @@ CenterFrames.toggle_frame(player,name,state) --- Toggles if the frame is currently open or not, will open if closed and close if open CenterFrames.new_frame(permision_name) --- Sets the frame to be the current active gui when opened and closes all other frames + CenterFrames._prototype:on_draw(player,frame) --- Use to draw your elements onto the new frame CenterFrames._prototype:set_auto_focus(state) --- Sets the frame to be the current active gui when opened and closes all other frames CenterFrames._prototype:draw_frame(player) --- Draws this frame to the player, if already open does nothing (will call on_draw to draw to the frame) CenterFrames._prototype:redraw_frame(player) --- Draws this frame to the player, if already open it will remove it and redraw it (will call on_draw to draw to the frame) diff --git a/expcore/Gui/left.lua b/expcore/Gui/left.lua index b3d431f3..45fb3bad 100644 --- a/expcore/Gui/left.lua +++ b/expcore/Gui/left.lua @@ -42,6 +42,8 @@ LeftFrames._prototype:redraw(player) --- Redraws the frame by calling on_draw, will always clear the frame LeftFrames._prototype:redraw_all(update_offline) --- Redraws the frame for all players, see redraw + LeftFrames._prototype:on_draw(player,frame) --- Use to draw your elements to the new frame + LeftFrames._prototype:on_update(player,frame) --- Use to edit your frame when there is no need to redraw it LeftFrames._prototype:event_handler(action) --- Creates an event handler that will trigger one of its functions, use with Event.add ]] local Gui = require 'expcore.gui.core' diff --git a/expcore/Gui/progress-bar.lua b/expcore/Gui/progress-bar.lua new file mode 100644 index 00000000..f5799fb4 --- /dev/null +++ b/expcore/Gui/progress-bar.lua @@ -0,0 +1,336 @@ +--- Gui element define for progess bars +--[[ +>>>> Functions + ProgressBar.set_maximum(element,amount,start_full) --- Sets the maximum value that represents the end value of the progress bar + ProgressBar.increment(element,amount) --- Increases the value of the progressbar, if a define is given all of its instances are incremented + ProgressBar.decrement(element,amount) --- Decreases the value of the progressbar, if a define is given all of its instances are decresed + + ProgressBar.new_progressbar(name) --- Creates a new progressbar element define + ProgressBar._prototype:set_maximum(amount,start_full) --- Sets the maximum value that represents the end value of the progress bar + ProgressBar._prototype:increment(amount,category) --- Increases the value of the progressbar + ProgressBar._prototype:decrement(amount,category) --- Decreases the value of the progressbar + ProgressBar._prototype:add_element(element) --- Adds an element into the list of instances that will are waiting to complete, does not work with store + ProgressBar._prototype:reset_element(element) --- Resets an element, or its store, to be back at the start, either 1 or 0 + + ProgressBar._prototype:on_complete() --- Triggers when a progress bar element compeltes (hits 0 or 1) + ProgressBar._prototype:on_complete() --- Triggers when a store value completes (hits 0 or 1) + ProgressBar._prototype:event_counter() --- Event handler factory that counts up by 1 every time the event triggeres + ProgressBar._prototype:event_countdown() --- Event handler factory that counts down by 1 every time the event triggeres +]] +local Gui = require 'expcore.gui.core' +local Global = require 'utils.global' +local Game = require 'utils.game' + +--- Event call for when the value is outside the range 0-1 +-- @tparam define table the define that this is acting on +-- @tparam element LuaGuiElement the element that triggered the event +local function event_call(define,element) + local player = Game.get_player_by_index(element.player_index) + + if define.events.on_complete then + define.events.on_complete(player,element,function() + define:add_element(element) + define:reset_element(element) + end) + end +end + +--- Store call for store update +-- @tparam define table the define that this is acting on +-- @tparam element LuaGuiElement the element that triggered the event +local function store_call(define,element,value) + element.value = value + if define.start_full and value <= 0 or not define.start_full and value >= 1 then + event_call(define,element) + end +end + +local ProgressBar = { + unregistered={}, + independent={}, + _prototype=Gui._prototype_factory{ + -- note both events will recive a reset function that can be used to reset the progress of the element/store + on_complete = Gui._event_factory('on_complete'), + on_store_complete = Gui._event_factory('on_store_complete'), + add_store = Gui._store_factory(store_call), + add_sync_store = Gui._sync_store_factory(store_call) + } +} +Global.register({ + ProgressBar.unregistered, + ProgressBar.independent +},function(tbl) + ProgressBar.unregistered = tbl[1] + ProgressBar.independent = tbl[2] +end) + +--- Gets the define data, cant use Gui.get_define as it would error +-- @tparam define ?table|string the define to get +-- @treturn table the define or nil +local function get_define(define) + if type(define) == 'table' then + if define.name and Gui.defines[define.name] then + return Gui.defines[define.name] + end + end + + return Gui.defines[define] +end + +--- Gets the element data, used when there is no define +-- @tparam element LuaGuiElement +-- @treturn table the element data simialr to define +local function get_element(element) + if not element.valid then return end + local name = element.player_index..':'..element.index + + if ProgressBar.unregistered[name] then + return ProgressBar.unregistered[name] + + else + ProgressBar.unregistered[name] = { + element=element, + maximum=1 + } + return ProgressBar.unregistered[name] + + end +end + +--- Sets the maximum value that represents the end value of the progress bar +-- @tparam element ?LuaGuiElement|string either a gui element or a registered define +-- @tparam amount number the amount to have set as the maximum +-- @tparam[opt=false] start_full boolean when true the bar will start filled, to be used with decrease +function ProgressBar.set_maximum(element,amount,start_full) + amount = amount > 0 and amount or error('amount must be greater than 0') + + local define = get_define(element) + if define then + define:set_maximum(amount,start_full) + + else + local element_data = get_element(element) + + if element_data then + element_data.maximum = amount + if start_full then + element.value = 1 + end + end + + end +end + +--- Increases the value of the progressbar, if a define is given all of its instances are incremented +-- @tapram element ?LuaGuiElement|string either a gui element or a registered define +-- @tparam[opt=1] amount number the amount to increase the progressbar by +function ProgressBar.increment(element,amount) + amount = type(amount) == 'number' and amount or 1 + + local define = get_define(element) + if define then + define:increment(amount) + + else + local element_data = get_element(element) + + if element_data then + local max = element_data.maximum > 0 and element_data.maximum or 1 + local real_amount = amount/max + element.value = element.value + real_amount + + if element.value >= 1 then + return true + end + end + + end +end + +--- Decreases the value of the progressbar, if a define is given all of its instances are decresed +-- @tapram element ?LuaGuiElement|string either a gui element or a registered define +-- @tparam[opt=1] amount number the amount to decrease the progressbar by +function ProgressBar.decrement(element,amount) + amount = type(amount) == 'number' and amount or 1 + + local define = get_define(element) + if define then + define:decrement(amount) + + else + local element_data = get_element(element) + + if element_data then + local max = element_data.maximum > 0 and element_data.maximum or 1 + local real_amount = amount/max + element.value = element.value - real_amount + + if element.value <= 0 then + return true + end + end + + end +end + +--- Creates a new progressbar element define +-- @tparam[opt] name string the optional debug name that can be added +-- @treturn table the new progressbar elemente define +function ProgressBar.new_progressbar(name) + local self = Gui._define_factory(ProgressBar._prototype) + self.draw_data.type = 'progressbar' + + if name then + self:debug_name(name) + end + + self.post_draw = function(element) + if self.store then + local category = self.categorize and self.categorize(element) or nil + local value = self:get_store(category) + if not value then + value = self.start_full and 1 or 0 + self:set_store(category,value) + end + element.value = value + + else + if self.start_full then + self.value = 1 + end + + if not ProgressBar.independent[self.name] then + ProgressBar.independent[self.name] = {} + end + + table.insert(ProgressBar.independent[self.name],element) + + end + + end + + return self +end + +--- Sets the maximum value that represents the end value of the progress bar +-- @tparam amount number the amount to have set as the maximum +-- @tparam[opt=false] start_full boolean when true the bar will start filled, to be used with decrease +function ProgressBar._prototype:set_maximum(amount,start_full) + amount = amount > 0 and amount or error('amount must be greater than 0') + self.maximum = amount + if start_full then + self.start_full = true + else + self.start_full = false + end + return self +end + +--- Main logic for changing the value of a progress bar, this only applies when its a registered define +-- @tparam self table the define that is being changed +-- @tparam amount number the amount which it is being changed by, may be negative +-- @tparam[opt] category string the category to use with store +local function change_value_prototype(self,amount,category) + + local function reset_store() + local value = self.start_full and 1 or 0 + local _category = category or value + self:set_store(_category,value) + end + + if self.store then + local value = self:get_store(category) or self.start_full and 1 or 0 + local new_value = value + amount + + if self.start_full and value <= 0 or not self.start_full and value >= 1 then + self:set_store(category) + if self.events.on_store_complete then + category = category or reset_store + self.events.on_store_complete(category,reset_store) + end + end + + category = category or new_value + self:set_store(category,new_value) + end + + if ProgressBar.independent[self.name] then + for key,element in pairs(ProgressBar.independent[self.name]) do + if not element or not element.valid then + ProgressBar.independent[self.name][key] = nil + else + element.value = element.value + amount + + if self.start_full and element.value <= 0 or not self.start_full and element.value >= 1 then + ProgressBar.independent[self.name][key] = nil + event_call(self,element) + end + end + end + end + +end + +--- Increases the value of the progressbar +-- @tparam[opt=1] amount number the amount to increase the progressbar by +-- @tparam[opt] category string the category that is used with a store +function ProgressBar._prototype:increment(amount,category) + amount = type(amount) == 'number' and amount or 1 + local max = self.maximum > 0 and self.maximum or 1 + local real_amount = amount/max + + change_value_prototype(self,real_amount,category) +end + +--- Decreases the value of the progressbar +-- @tparam[opt=1] amount number the amount to decrease the progressbar by +-- @tparam[opt] category string the category that is used with a store +function ProgressBar._prototype:decrement(amount,category) + amount = type(amount) == 'number' and amount or 1 + local max = self.maximum > 0 and self.maximum or 1 + local real_amount = amount/max + + change_value_prototype(self,-real_amount,category) +end + +--- Adds an element into the list of instances that will are waiting to complete, does not work with store +-- note use store if you want persistent data, this only stores the elements not the values which they have +-- @tparam element LuaGuiElement the element that you want to add into the waiting to complete list +function ProgressBar._prototype:add_element(element) + if self.store then return end + if not ProgressBar.independent[self.name] then + ProgressBar.independent[self.name] = {} + end + table.insert(ProgressBar.independent[self.name],element) +end + +--- Resets an element, or its store, to be back at the start, either 1 or 0 +-- @tparam element LuaGuiElement the element that you want to reset the progress of +function ProgressBar._prototype:reset_element(element) + if not element or not element.valid then return end + local value = self.start_full and 1 or 0 + if self.store then + local category = self.categorize and self.categorize(element) or value + self:set_store(category,value) + else + element.value = value + end +end + +--- Event handler factory that counts up by 1 every time the event triggeres +-- @treturn function the event handler +function ProgressBar._prototype:event_counter() + return function() + self:increment() + end +end + +--- Event handler factory that counts down by 1 every time the event triggeres +-- @treturn function the event handler +function ProgressBar._prototype:event_countdown() + return function() + self:decrement() + end +end + +return ProgressBar \ No newline at end of file diff --git a/expcore/Gui/test.lua b/expcore/Gui/test.lua index 31b289f2..d227d10c 100644 --- a/expcore/Gui/test.lua +++ b/expcore/Gui/test.lua @@ -5,6 +5,7 @@ local Gui = require 'expcore.gui' local format_chat_colour,table_keys = ext_require('expcore.common','format_chat_colour','table_keys') local Colors = require 'resources.color_presets' local Event = require 'utils.event' +local Store = require 'expcore.store' local tests = {} @@ -572,4 +573,51 @@ tests["Elem Buttons"] = { ['Default']=elem_default, ['Function']=elem_function, ['Store']=elem_store +} + +--[[ + Progress bar tests + > Simple -- Progress bar that fills every 2 seconds + > Store -- Progress bar that fills every 5 seconds with synced value + > Reverce -- Progress bar that decreases every 2 seconds +]] + +local progressbar_one = +Gui.new_progressbar('test-prog-one') +:set_maximum(120) +:on_complete(function(player,element,reset_element) + reset_element() +end) + +local progressbar_two = +Gui.new_progressbar('test-prog-one') +:set_maximum(300) +:add_store(Gui.force_store) +:on_complete(function(player,element,reset_element) + reset_element() +end) +:on_store_complete(function(category,reset_store) + reset_store() +end) + +local progressbar_three = +Gui.new_progressbar('test-prog-one') +:set_maximum(120,true) +:on_complete(function(player,element,reset_element) + reset_element() +end) + +Event.add(defines.events.on_tick,function() + progressbar_one:increment() + progressbar_three:decrement() + local categories = Store.get_children(progressbar_two.store) + for category,_ in pairs(categories) do + progressbar_two:increment(1,category) + end +end) + +tests["Progress Bars"] = { + ['Simple']=progressbar_one, + ['Store']=progressbar_two, + ['Reverce']=progressbar_three } \ No newline at end of file diff --git a/expcore/gui.lua b/expcore/gui.lua index 6568e744..09363b24 100644 --- a/expcore/gui.lua +++ b/expcore/gui.lua @@ -143,6 +143,29 @@ Gui.classes.elem_button = ElemButton ElemButton._prototype:set_default(value) --- Sets the default value for the elem button, this may be a function or a string ]] +local ProgressBar = require 'expcore.gui.progress-bar' +Gui.new_progressbar = ProgressBar.new_progressbar +Gui.set_progressbar_maximum = ProgressBar.set_maximum +Gui.increment_progressbar = ProgressBar.increment +Gui.decrement_progressbar = ProgressBar.decrement +--[[ + ProgressBar.set_maximum(element,amount,start_full) --- Sets the maximum value that represents the end value of the progress bar + ProgressBar.increment(element,amount) --- Increases the value of the progressbar, if a define is given all of its instances are incremented + ProgressBar.decrement(element,amount) --- Decreases the value of the progressbar, if a define is given all of its instances are decresed + + ProgressBar.new_progressbar(name) --- Creates a new progressbar element define + ProgressBar._prototype:set_maximum(amount,start_full) --- Sets the maximum value that represents the end value of the progress bar + ProgressBar._prototype:increment(amount,category) --- Increases the value of the progressbar + ProgressBar._prototype:decrement(amount,category) --- Decreases the value of the progressbar + ProgressBar._prototype:add_element(element) --- Adds an element into the list of instances that will are waiting to complete, does not work with store + ProgressBar._prototype:reset_element(element) --- Resets an element, or its store, to be back at the start, either 1 or 0 + + ProgressBar._prototype:on_complete() --- Triggers when a progress bar element compeltes (hits 0 or 1) + ProgressBar._prototype:on_complete() --- Triggers when a store value completes (hits 0 or 1) + ProgressBar._prototype:event_counter() --- Event handler factory that counts up by 1 every time the event triggeres + ProgressBar._prototype:event_countdown() --- Event handler factory that counts down by 1 every time the event triggeres +]] + local Toolbar = require 'expcore.gui.toolbar' Gui.new_toolbar_button = Toolbar.new_button Gui.add_button_to_toolbar = Toolbar.add_button @@ -176,6 +199,8 @@ Gui.classes.left_frames = LeftFrames LeftFrames._prototype:redraw(player) --- Redraws the frame by calling on_draw, will always clear the frame LeftFrames._prototype:redraw_all(update_offline) --- Redraws the frame for all players, see redraw + LeftFrames._prototype:on_draw(player,frame) --- Use to draw your elements to the new frame + LeftFrames._prototype:on_update(player,frame) --- Use to edit your frame when there is no need to redraw it LeftFrames._prototype:event_handler(action) --- Creates an event handler that will trigger one of its functions, use with Event.add ]] @@ -194,6 +219,7 @@ Gui.classes.center_frames = CenterFrames CenterFrames.toggle_frame(player,name,state) --- Toggles if the frame is currently open or not, will open if closed and close if open CenterFrames.new_frame(permision_name) --- Sets the frame to be the current active gui when opened and closes all other frames + CenterFrames._prototype:on_draw(player,frame) --- Use to draw your elements onto the new frame CenterFrames._prototype:set_auto_focus(state) --- Sets the frame to be the current active gui when opened and closes all other frames CenterFrames._prototype:draw_frame(player) --- Draws this frame to the player, if already open does nothing (will call on_draw to draw to the frame) CenterFrames._prototype:redraw_frame(player) --- Draws this frame to the player, if already open it will remove it and redraw it (will call on_draw to draw to the frame) From 23b54913d4f437ae24984057b950686f219e9186 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Fri, 24 May 2019 20:02:18 +0100 Subject: [PATCH 8/8] Added popup frames --- expcore/Gui/core.lua | 26 +++- expcore/Gui/instances.lua | 4 +- expcore/Gui/left.lua | 8 +- expcore/Gui/popups.lua | 228 +++++++++++++++++++++++++++++++++++ expcore/Gui/progress-bar.lua | 196 +++++++++++++++++++----------- expcore/Gui/slider.lua | 12 ++ expcore/Gui/test.lua | 44 ++++++- expcore/gui.lua | 36 ++++-- 8 files changed, 460 insertions(+), 94 deletions(-) create mode 100644 expcore/Gui/popups.lua diff --git a/expcore/Gui/core.lua b/expcore/Gui/core.lua index 16c9fe5a..07d7e8f7 100644 --- a/expcore/Gui/core.lua +++ b/expcore/Gui/core.lua @@ -278,8 +278,8 @@ function Gui._define_factory(prototype) } },{ __index=prototype, - __call=function(self,element) - return self:draw_to(element) + __call=function(self,element,...) + return self:draw_to(element,...) end }) Gui.defines[define.name] = define @@ -350,7 +350,7 @@ end -- the data with in the draw_data is set up through the use of all the other functions -- @tparam element LuaGuiElement the element that the define will draw a copy of its self onto -- @treturn LuaGuiElement the new element that was drawn so styles can be applied -function Gui._prototype:draw_to(element) +function Gui._prototype:draw_to(element,...) if element[self.name] then return end local player = Game.get_player_by_index(element.player_index) @@ -368,7 +368,7 @@ function Gui._prototype:draw_to(element) Instances.add_element(self.name,new_element) end - if self.post_draw then self.post_draw(new_element) end + if self.post_draw then self.post_draw(new_element,...) end return new_element end @@ -469,9 +469,9 @@ end -- @tparam name ?string|table the uid, debug name or define for the element define to draw -- @tparam element LuaGuiEelement the parent element that it the define will be drawn to -- @treturn LuaGuiElement the new element that was created -function Gui.draw(name,element) +function Gui.draw(name,element,...) local define = Gui.get_define(name,true) - return define:draw_to(element) + return define:draw_to(element,...) end --- Will toggle the enabled state of an element @@ -496,4 +496,18 @@ function Gui.toggle_visible(element) end end +--- Sets the padding for a gui element +-- @tparam element LuaGuiElement the element to set the padding for +-- @tparam[opt=0] up number the amount of padding on the top +-- @tparam[opt=0] down number the amount of padding on the bottom +-- @tparam[opt=0] left number the amount of padding on the left +-- @tparam[opt=0] right number the amount of padding on the right +function Gui.set_padding(element,up,down,left,right) + local style = element.style + style.top_padding = up or 0 + style.bottom_padding = down or 0 + style.left_padding = left or 0 + style.right_padding = right or 0 +end + return Gui \ No newline at end of file diff --git a/expcore/Gui/instances.lua b/expcore/Gui/instances.lua index c1abecd0..7e0fde9f 100644 --- a/expcore/Gui/instances.lua +++ b/expcore/Gui/instances.lua @@ -206,8 +206,8 @@ end -- @treturn table the table of element instances with all invalid ones removed function Instances.unregistered_get_elements(name,category,callback) local elements = Instances.data[name] - if category then - elements = Instances.data[name][category] + if elements and category then + elements = elements[category] end if not elements then return {} end diff --git a/expcore/Gui/left.lua b/expcore/Gui/left.lua index 45fb3bad..da7f37e4 100644 --- a/expcore/Gui/left.lua +++ b/expcore/Gui/left.lua @@ -253,13 +253,11 @@ Event.add(defines.events.on_player_created,function(event) local player = Game.get_player_by_index(event.player_index) local flow = LeftFrames.get_flow(player) - local style = LeftFrames.toggle_button(flow).style + local close_button = LeftFrames.toggle_button(flow) + Gui.set_padding(close_button) + local style = close_button.style style.width = 18 style.height = 36 - style.left_padding = 0 - style.top_padding = 0 - style.right_padding = 0 - style.bottom_padding = 0 style.font = 'default-small-bold' for _,define in pairs(LeftFrames.frames) do diff --git a/expcore/Gui/popups.lua b/expcore/Gui/popups.lua new file mode 100644 index 00000000..fa0c0668 --- /dev/null +++ b/expcore/Gui/popups.lua @@ -0,0 +1,228 @@ +--- Gui structure define for popup gui +--[[ +>>>> Functions + PopupFrames.get_flow(player) --- Gets the left flow that contains the popup frames + PopupFrames.open(define_name,player,open_time,...) --- Opens a popup for the player, can give the amount of time it is open as well as params for the draw function + + PopupFrames.close_progress --- Progress bar which when depleaded will close the popup frame + PopupFrames.close_button --- A button which can be used to close the gui before the timer runs out + + PopupFrames.new_popup(name) --- Creates a new popup frame define + PopupFrames._prototype:set_default_open_time(amount) --- Sets the default open time for the popup, will be used if non is provided with open + PopupFrames._prototype:open(player,open_time,...) --- Opens this define for a player, can be given open time and any other params for the draw function +]] +local Gui = require 'expcore.gui.core' +local Game = require 'utils.game' +local Event = require 'utils.event' +local ProgressBar = require 'expcore.gui.progress-bar' +local Button = require 'expcore.gui.buttons' +local mod_gui = require 'mod-gui' +local Color = require 'resources.color_presets' +local Global = require 'utils.global' + +local PopupFrames = { + paused_popups={}, + popup_flow_name = Gui.uid_name(), + main_frame_name = Gui.uid_name(), + close_frame_name = Gui.uid_name(), + _prototype = Gui._prototype_factory{ + on_draw = Gui._event_factory('on_draw') + } +} +Global.register(PopupFrames.paused_popups,function(tbl) + PopupFrames.paused_popups = tbl +end) + +--- Sets the state of the element in the pasued list, nil or true +-- @tparam element LuaGuiElement the element to set the state of +-- @tparam[opt] state boolean the state to set it to, true will pause the the progress bar +local function set_pasued_state(element,state) + local name = element.player_index..':'..element.index + PopupFrames.paused_popups[name] = state +end + +--- Gets the state of the element in the pasued list, nil or true +-- @tparam element LuaGuiElement the element to get the state of +local function get_pasued_state(element) + local name = element.player_index..':'..element.index + return PopupFrames.paused_popups[name] +end + +--- Gets the left flow that contains the popup frames +-- @tparam player LuaPlayer the player to get the flow for +-- @treturn LuaGuiElement the left flow that contains the popup frames +function PopupFrames.get_flow(player) + player = Game.get_player_from_any(player) + local flow = mod_gui.get_frame_flow(player) + return flow[PopupFrames.popup_flow_name] +end + +--- Opens a popup for the player, can give the amount of time it is open as well as params for the draw function +-- @tparam define_name string the name of the define that you want to open for the player +-- @tparam player LuaPlayer the player to open the popup for +-- @tparam[opt] open_time number the minimum number of ticks you want the popup open for, 0 means no limit, nil will take default +-- @tparam ... any the other params that you want to pass to your on_draw event +-- @treturn LuaGuiElement the frame that was drawn, the inner gui flow which contains the content +function PopupFrames.open(define_name,player,open_time,...) + local define = Gui.get_define(define_name,true) + player = Game.get_player_from_any(player) + return define:open(player,open_time,...) +end + +--- Closes the popup, is called by progress bar and close button +-- @tparam element LuaGuiElement either the progress bar or the close button +local function close_popup(element) + local frame = element.parent.parent.parent + if not frame or not frame.valid then return end + set_pasued_state(element.parent[PopupFrames.close_progress:uid()]) + frame.destroy() +end + +--- Progress bar which when depleaded will close the popup frame +PopupFrames.close_progress = +ProgressBar.new_progressbar() +:use_count_down() +:set_tooltip('Pause/Resume Auto-close') +:on_complete(function(player,element) + close_popup(element) +end) + +--- A button which can be used to close the gui before the timer runs out +PopupFrames.close_button = +Button.new_button() +:set_sprites('utility/close_white') +:set_tooltip('Close Popup') +:on_click(function(player,element) + close_popup(element) +end) + +--- When the progress bar is clicked it will pause its progress, or resume if previously paused +Gui.on_click(PopupFrames.close_progress:uid(),function(event) + local element = event.element + if get_pasued_state(element) then + set_pasued_state(element) + else + set_pasued_state(element,true) + end +end) + +--- When the parent flow of the progress bar is clicked it will pause its progress, or resume if previously paused +Gui.on_click(PopupFrames.close_frame_name,function(event) + local element = event.element[PopupFrames.close_progress:uid()] + if get_pasued_state(element) then + set_pasued_state(element) + else + set_pasued_state(element,true) + end +end) + +--- Creates a new popup frame define +-- @tparam[opt] name string the optional debug name that can be added +-- @treturn table the new popup frame define +function PopupFrames.new_popup(name) + local self = Gui._define_factory(PopupFrames._prototype) + self.draw_data.type = 'flow' + self.draw_data.direction = 'vertical' + + if name then + self:debug_name(name) + end + + local mt = getmetatable(self) + mt.__call = function(tbl,player,open_time,...) + return tbl:open(player,open_time,...) + end + + self.post_draw = function(element,maximum,...) + -- main content frame + local frame = element.add{ + type='flow', + name=PopupFrames.main_frame_name + } + frame.style.horizontally_stretchable = true + + -- flow for progress bar and close button + local close_flow = element.add{ + type='flow', + name=PopupFrames.close_frame_name + } + close_flow.style.horizontally_stretchable = true + + -- progress bar, when 0 then a static full one is drawn + local progress_style + if maximum == 0 then + progress_style = close_flow.add{ + type='progressbar', + tooltip='No Auto-close', + value=1 + }.style + else + progress_style = PopupFrames.close_progress(close_flow,maximum).style + end + progress_style.top_padding = 6 + progress_style.bottom_padding = 3 + progress_style.height = 11 + progress_style.color = Color.grey + + -- close button, will close the popup when clicked + local close_button = PopupFrames.close_button(close_flow) + Gui.set_padding(close_button) + local close_button_style = close_button.style + close_button_style.width = 20 + close_button_style.height = 20 + + -- event trigger to draw the gui content + if self.events.on_draw then + local player = Game.get_player_by_index(element.player_index) + self.events.on_draw(player,frame,...) + end + end + + return self +end + +--- Sets the default open time for the popup, will be used if non is provided with open +-- @tparam amount number the number of ticks, by default, the popup will be open for +-- @treturn table the define to allow for chaining +function PopupFrames._prototype:set_default_open_time(amount) + self.default_open_time = amount + return self +end + +--- Opens this define for a player, can be given open time and any other params for the draw function +-- @tparam player LuaPlayer the player to open the popup for +-- @tparam[opt] open_time number the minimum number of ticks you want the popup open for, 0 means no limit, nil will take default +-- @tparam ... any the other params that you want to pass to your on_draw event +-- @treturn LuaGuiElement the frame that was drawn, the inner gui flow which contains the content +function PopupFrames._prototype:open(player,open_time,...) + open_time = open_time or self.default_open_time or 0 + player = Game.get_player_from_any(player) + + local flow = PopupFrames.get_flow(player) + local frame = flow.add{ + type='frame', + style='blurry_frame' + } + + Gui.set_padding(frame,3,3,4,4) + return self:draw_to(frame,open_time,...)[PopupFrames.main_frame_name] +end + +--- When player is first created the popup flow is added to they left flow +Event.add(defines.events.on_player_created,function(event) + local player = Game.get_player_by_index(event.player_index) + local flow = mod_gui.get_frame_flow(player) + + flow.add{ + type='flow', + direction='vertical', + name=PopupFrames.popup_flow_name + } +end) + +--- Every tick any, not pasued, progress bars will go down by one tick +Event.add(defines.events.on_tick,PopupFrames.close_progress:event_countdown(function(element) + return not get_pasued_state(element) +end)) + +return PopupFrames \ No newline at end of file diff --git a/expcore/Gui/progress-bar.lua b/expcore/Gui/progress-bar.lua index f5799fb4..6944fb8e 100644 --- a/expcore/Gui/progress-bar.lua +++ b/expcore/Gui/progress-bar.lua @@ -1,21 +1,24 @@ --- Gui element define for progess bars --[[ >>>> Functions - ProgressBar.set_maximum(element,amount,start_full) --- Sets the maximum value that represents the end value of the progress bar + ProgressBar.set_maximum(element,amount,count_down) --- Sets the maximum value that represents the end value of the progress bar ProgressBar.increment(element,amount) --- Increases the value of the progressbar, if a define is given all of its instances are incremented ProgressBar.decrement(element,amount) --- Decreases the value of the progressbar, if a define is given all of its instances are decresed ProgressBar.new_progressbar(name) --- Creates a new progressbar element define - ProgressBar._prototype:set_maximum(amount,start_full) --- Sets the maximum value that represents the end value of the progress bar + ProgressBar._prototype:set_maximum(amount,count_down) --- Sets the maximum value that represents the end value of the progress bar + ProgressBar._prototype:use_count_down(state) --- Will set the progress bar to start at 1 and trigger when it hits 0 ProgressBar._prototype:increment(amount,category) --- Increases the value of the progressbar + ProgressBar._prototype:increment_filtered(amount,filter) --- Increases the value of the progressbar, if the filter condition is met, does not work with store ProgressBar._prototype:decrement(amount,category) --- Decreases the value of the progressbar - ProgressBar._prototype:add_element(element) --- Adds an element into the list of instances that will are waiting to complete, does not work with store + ProgressBar._prototype:decrement_filtered(amount,filter) --- Decreases the value of the progressbar, if the filter condition is met, does not work with store + ProgressBar._prototype:add_element(element,maximum) --- Adds an element into the list of instances that will are waiting to complete, does not work with store ProgressBar._prototype:reset_element(element) --- Resets an element, or its store, to be back at the start, either 1 or 0 - ProgressBar._prototype:on_complete() --- Triggers when a progress bar element compeltes (hits 0 or 1) - ProgressBar._prototype:on_complete() --- Triggers when a store value completes (hits 0 or 1) - ProgressBar._prototype:event_counter() --- Event handler factory that counts up by 1 every time the event triggeres - ProgressBar._prototype:event_countdown() --- Event handler factory that counts down by 1 every time the event triggeres + ProgressBar._prototype:on_complete(callback) --- Triggers when a progress bar element compeltes (hits 0 or 1) + ProgressBar._prototype:on_complete(callback) --- Triggers when a store value completes (hits 0 or 1) + ProgressBar._prototype:event_counter(filter) --- Event handler factory that counts up by 1 every time the event triggeres, can filter which elements are incremented + ProgressBar._prototype:event_countdown(filter) --- Event handler factory that counts down by 1 every time the event triggeres, can filter which elements are decremented ]] local Gui = require 'expcore.gui.core' local Global = require 'utils.global' @@ -39,15 +42,18 @@ end -- @tparam define table the define that this is acting on -- @tparam element LuaGuiElement the element that triggered the event local function store_call(define,element,value) - element.value = value - if define.start_full and value <= 0 or not define.start_full and value >= 1 then - event_call(define,element) + if value then + element.value = value + if define.count_down and value <= 0 + or not define.count_down and value >= 1 then + event_call(define,element) + end end end local ProgressBar = { - unregistered={}, - independent={}, + unregistered={}, -- elements with no callbacks + independent={}, -- elements with a link to a deinfe _prototype=Gui._prototype_factory{ -- note both events will recive a reset function that can be used to reset the progress of the element/store on_complete = Gui._event_factory('on_complete'), @@ -86,36 +92,32 @@ local function get_element(element) if ProgressBar.unregistered[name] then return ProgressBar.unregistered[name] - - else - ProgressBar.unregistered[name] = { - element=element, - maximum=1 - } - return ProgressBar.unregistered[name] - end end --- Sets the maximum value that represents the end value of the progress bar -- @tparam element ?LuaGuiElement|string either a gui element or a registered define -- @tparam amount number the amount to have set as the maximum --- @tparam[opt=false] start_full boolean when true the bar will start filled, to be used with decrease -function ProgressBar.set_maximum(element,amount,start_full) +function ProgressBar.set_maximum(element,amount) amount = amount > 0 and amount or error('amount must be greater than 0') local define = get_define(element) if define then - define:set_maximum(amount,start_full) + define:set_deafult_maximum(amount) else local element_data = get_element(element) if element_data then element_data.maximum = amount - if start_full then - element.value = 1 - end + + else + local name = element.player_index..':'..element.index + ProgressBar.unregistered[name] = { + element=element, + maximum=amount or 1 + } + end end @@ -135,11 +137,12 @@ function ProgressBar.increment(element,amount) local element_data = get_element(element) if element_data then - local max = element_data.maximum > 0 and element_data.maximum or 1 - local real_amount = amount/max + local real_amount = amount/element_data.maximum element.value = element.value + real_amount if element.value >= 1 then + local name = element.player_index..':'..element.index + ProgressBar.unregistered[name] = nil return true end end @@ -161,11 +164,12 @@ function ProgressBar.decrement(element,amount) local element_data = get_element(element) if element_data then - local max = element_data.maximum > 0 and element_data.maximum or 1 - local real_amount = amount/max + local real_amount = amount/element_data.maximum element.value = element.value - real_amount if element.value <= 0 then + local name = element.player_index..':'..element.index + ProgressBar.unregistered[name] = nil return true end end @@ -184,26 +188,29 @@ function ProgressBar.new_progressbar(name) self:debug_name(name) end - self.post_draw = function(element) + self.post_draw = function(element,maximum) if self.store then local category = self.categorize and self.categorize(element) or nil local value = self:get_store(category) if not value then - value = self.start_full and 1 or 0 + value = self.count_down and 1 or 0 self:set_store(category,value) end element.value = value else - if self.start_full then - self.value = 1 + if self.count_down then + element.value = 1 end if not ProgressBar.independent[self.name] then ProgressBar.independent[self.name] = {} end - table.insert(ProgressBar.independent[self.name],element) + table.insert(ProgressBar.independent[self.name],{ + element = element, + maximum = maximum + }) end @@ -214,36 +221,46 @@ end --- Sets the maximum value that represents the end value of the progress bar -- @tparam amount number the amount to have set as the maximum --- @tparam[opt=false] start_full boolean when true the bar will start filled, to be used with decrease -function ProgressBar._prototype:set_maximum(amount,start_full) +-- @treturn table the define to allow chaining +function ProgressBar._prototype:set_default_maximum(amount) amount = amount > 0 and amount or error('amount must be greater than 0') - self.maximum = amount - if start_full then - self.start_full = true - else - self.start_full = false - end + self.default_maximum = amount return self end +--- Will set the progress bar to start at 1 and trigger when it hits 0 +-- @tparam[opt=true] state boolean when true the bar will start filled, to be used with decrease +-- @treturn table the define to allow chaining +function ProgressBar._prototype:use_count_down(state) + if state == false then + self.count_down = false + else + self.count_down = true + end + return self +end + --- Main logic for changing the value of a progress bar, this only applies when its a registered define -- @tparam self table the define that is being changed -- @tparam amount number the amount which it is being changed by, may be negative -- @tparam[opt] category string the category to use with store -local function change_value_prototype(self,amount,category) +local function change_value_prototype(self,amount,category,filter) local function reset_store() - local value = self.start_full and 1 or 0 + local value = self.count_down and 1 or 0 local _category = category or value self:set_store(_category,value) end if self.store then - local value = self:get_store(category) or self.start_full and 1 or 0 - local new_value = value + amount + local value = self:get_store(category) or self.count_down and 1 or 0 + local maximum = self.default_maximum or 1 + local new_value = value + (amount/maximum) - if self.start_full and value <= 0 or not self.start_full and value >= 1 then + if self.count_down and new_value <= 0 + or not self.count_down and new_value >= 1 then self:set_store(category) + if self.events.on_store_complete then category = category or reset_store self.events.on_store_complete(category,reset_store) @@ -252,19 +269,28 @@ local function change_value_prototype(self,amount,category) category = category or new_value self:set_store(category,new_value) + + return end if ProgressBar.independent[self.name] then - for key,element in pairs(ProgressBar.independent[self.name]) do + for key,element_data in pairs(ProgressBar.independent[self.name]) do + local element = element_data.element if not element or not element.valid then ProgressBar.independent[self.name][key] = nil - else - element.value = element.value + amount - if self.start_full and element.value <= 0 or not self.start_full and element.value >= 1 then - ProgressBar.independent[self.name][key] = nil - event_call(self,element) + else + if not filter or filter(element) then + local maximum = element_data.maximum or self.default_maximum or 1 + element.value = element.value + (amount/maximum) + + if self.count_down and element.value <= 0 + or not self.count_down and element.value >= 1 then + ProgressBar.independent[self.name][key] = nil + event_call(self,element) + end end + end end end @@ -276,10 +302,15 @@ end -- @tparam[opt] category string the category that is used with a store function ProgressBar._prototype:increment(amount,category) amount = type(amount) == 'number' and amount or 1 - local max = self.maximum > 0 and self.maximum or 1 - local real_amount = amount/max + change_value_prototype(self,amount,category) +end - change_value_prototype(self,real_amount,category) +--- Increases the value of the progressbar, if the filter condition is met, does not work with store +-- @tparam[opt=1] amount number the amount to increase the progressbar by +-- @tparam[opt] category string the category that is used with a store +function ProgressBar._prototype:increment_filtered(amount,filter) + amount = type(amount) == 'number' and amount or 1 + change_value_prototype(self,amount,nil,filter) end --- Decreases the value of the progressbar @@ -287,28 +318,37 @@ end -- @tparam[opt] category string the category that is used with a store function ProgressBar._prototype:decrement(amount,category) amount = type(amount) == 'number' and amount or 1 - local max = self.maximum > 0 and self.maximum or 1 - local real_amount = amount/max + change_value_prototype(self,-amount,category) +end - change_value_prototype(self,-real_amount,category) +--- Decreases the value of the progressbar, if the filter condition is met, does not work with store +-- @tparam[opt=1] amount number the amount to decrease the progressbar by +-- @tparam[opt] category string the category that is used with a store +function ProgressBar._prototype:decrement_filtered(amount,filter) + amount = type(amount) == 'number' and amount or 1 + change_value_prototype(self,-amount,nil,filter) end --- Adds an element into the list of instances that will are waiting to complete, does not work with store -- note use store if you want persistent data, this only stores the elements not the values which they have -- @tparam element LuaGuiElement the element that you want to add into the waiting to complete list -function ProgressBar._prototype:add_element(element) +-- @tparam[opt] maximum number the maximum for this element if not given the default for this define is used +function ProgressBar._prototype:add_element(element,maximum) if self.store then return end if not ProgressBar.independent[self.name] then ProgressBar.independent[self.name] = {} end - table.insert(ProgressBar.independent[self.name],element) + table.insert(ProgressBar.independent[self.name],{ + element = element, + maximum = maximum + }) end --- Resets an element, or its store, to be back at the start, either 1 or 0 -- @tparam element LuaGuiElement the element that you want to reset the progress of function ProgressBar._prototype:reset_element(element) if not element or not element.valid then return end - local value = self.start_full and 1 or 0 + local value = self.count_down and 1 or 0 if self.store then local category = self.categorize and self.categorize(element) or value self:set_store(category,value) @@ -317,19 +357,33 @@ function ProgressBar._prototype:reset_element(element) end end ---- Event handler factory that counts up by 1 every time the event triggeres +--- Event handler factory that counts up by 1 every time the event triggeres, can filter which elements are incremented +-- @tparam[opt] filter function when given will use filtered incerement -- @treturn function the event handler -function ProgressBar._prototype:event_counter() - return function() - self:increment() +function ProgressBar._prototype:event_counter(filter) + if type(filter) == 'function' then + return function() + self:increment_filtered(1,filter) + end + else + return function() + self:increment() + end end end ---- Event handler factory that counts down by 1 every time the event triggeres +--- Event handler factory that counts down by 1 every time the event triggeres, can filter which elements are decremented +-- @tparam[opt] filter function when given will use filtered decerement -- @treturn function the event handler -function ProgressBar._prototype:event_countdown() - return function() - self:decrement() +function ProgressBar._prototype:event_countdown(filter) + if type(filter) == 'function' then + return function() + self:decrement_filtered(1,filter) + end + else + return function() + self:decrement() + end end end diff --git a/expcore/Gui/slider.lua b/expcore/Gui/slider.lua index c0182369..7c0df3ee 100644 --- a/expcore/Gui/slider.lua +++ b/expcore/Gui/slider.lua @@ -6,6 +6,7 @@ Slider._prototype:on_element_update(callback) --- Registers a handler for when an element instance updates Slider._prototype:on_store_update(callback) --- Registers a handler for when the stored value updates + Slider._prototype:use_notches(state) --- Adds notches to the slider Slider._prototype:set_range(min,max) --- Sets the range of a slider, if not used will use default values for a slider Slider._prototype:draw_label(element) --- Draws a new label and links its value to the value of this slider, if no store then it will only show one value per player Slider._prototype:enable_auto_draw_label(state) --- Enables auto draw of the label, the label will share the same parent element as the slider @@ -114,6 +115,17 @@ function Slider.new_slider(name) return self end +--- Adds notches to the slider +-- @tparam[opt] state boolean when true will draw notches onto the slider +function Slider._prototype:use_notches(state) + if state == false then + self.draw_data.style = nil + else + self.draw_data.style = 'notched_slider' + end + return self +end + --- Sets the range of a slider, if not used will use default values for a slider -- @tparam[opt] min number the minimum value that the slider can take -- @tparam[opt] max number the maximum value that the slider can take diff --git a/expcore/Gui/test.lua b/expcore/Gui/test.lua index d227d10c..a4e7701f 100644 --- a/expcore/Gui/test.lua +++ b/expcore/Gui/test.lua @@ -116,6 +116,33 @@ end) Event.add(defines.events.on_player_joined_game,left_frame 'update_all') Event.add(defines.events.on_player_left_game,left_frame 'update_all') +--[[ + Popup Test + > Allows opening a popup which contains the players name and tick it was opened +]] + +local test_popup = +Gui.new_popup('test-popup') +:on_draw(function(player,frame) + frame.add{ + type='label', + caption=player.name + } + frame.add{ + type='label', + caption=game.tick + } +end) + +Gui.new_toolbar_button('test-popup-open') +:set_caption('Test Popup') +:set_post_authenticator(function(player,button_name) + return global.show_test_gui +end) +:on_click(function(player,element) + test_popup(player,300) +end) + --[[ Button Tests > No display - Simple button which has no display @@ -403,6 +430,7 @@ tests["List Boxs"] = { --[[ Slider Tests > Local default -- Simple slider with default range + > Local notched -- Simple slider with notches > Store default -- Slider with default range that stores value between re-draws > Static range -- Simple slider with a static range > Dynamic range -- Slider with a dynamic range @@ -417,6 +445,14 @@ Gui.new_slider('test-slider-local-default') player.print('Slider local default: '..tostring(math.round(value))..' '..tostring(math.round(percent,1))) end) +local slider_notched_default = +Gui.new_slider('test-slider-notched-default') +:set_tooltip('Silder notched default') +:use_notches() +:on_element_update(function(player,element,value,percent) + player.print('Slider notched default: '..tostring(math.round(value))..' '..tostring(math.round(percent,1))) +end) + local slider_player_default = Gui.new_slider('test-slider-store-default') :set_tooltip('Silder store default') @@ -464,6 +500,7 @@ end) tests.Sliders = { ['Local default']=slider_local_default, + ['Local notched']=slider_notched_default, ['Player default']=slider_player_default, ['Static range']=slider_static, ['Dynamic range']=slider_dynamic, @@ -584,14 +621,14 @@ tests["Elem Buttons"] = { local progressbar_one = Gui.new_progressbar('test-prog-one') -:set_maximum(120) +:set_default_maximum(120) :on_complete(function(player,element,reset_element) reset_element() end) local progressbar_two = Gui.new_progressbar('test-prog-one') -:set_maximum(300) +:set_default_maximum(300) :add_store(Gui.force_store) :on_complete(function(player,element,reset_element) reset_element() @@ -602,7 +639,8 @@ end) local progressbar_three = Gui.new_progressbar('test-prog-one') -:set_maximum(120,true) +:set_default_maximum(120) +:use_count_down() :on_complete(function(player,element,reset_element) reset_element() end) diff --git a/expcore/gui.lua b/expcore/gui.lua index 09363b24..5831acf8 100644 --- a/expcore/gui.lua +++ b/expcore/gui.lua @@ -108,6 +108,7 @@ Gui.classes.slider = Slider Slider._prototype:on_element_update(callback) --- Registers a handler for when an element instance updates Slider._prototype:on_store_update(callback) --- Registers a handler for when the stored value updates + Slider._prototype:use_notches(state) --- Adds notches to the slider Slider._prototype:set_range(min,max) --- Sets the range of a slider, if not used will use default values for a slider Slider._prototype:draw_label(element) --- Draws a new label and links its value to the value of this slider, if no store then it will only show one value per player Slider._prototype:enable_auto_draw_label(state) --- Enables auto draw of the label, the label will share the same parent element as the slider @@ -148,22 +149,26 @@ Gui.new_progressbar = ProgressBar.new_progressbar Gui.set_progressbar_maximum = ProgressBar.set_maximum Gui.increment_progressbar = ProgressBar.increment Gui.decrement_progressbar = ProgressBar.decrement +Gui.classes.progressbar = ProgressBar --[[ - ProgressBar.set_maximum(element,amount,start_full) --- Sets the maximum value that represents the end value of the progress bar + ProgressBar.set_maximum(element,amount,count_down) --- Sets the maximum value that represents the end value of the progress bar ProgressBar.increment(element,amount) --- Increases the value of the progressbar, if a define is given all of its instances are incremented ProgressBar.decrement(element,amount) --- Decreases the value of the progressbar, if a define is given all of its instances are decresed ProgressBar.new_progressbar(name) --- Creates a new progressbar element define - ProgressBar._prototype:set_maximum(amount,start_full) --- Sets the maximum value that represents the end value of the progress bar + ProgressBar._prototype:set_maximum(amount,count_down) --- Sets the maximum value that represents the end value of the progress bar + ProgressBar._prototype:use_count_down(state) --- Will set the progress bar to start at 1 and trigger when it hits 0 ProgressBar._prototype:increment(amount,category) --- Increases the value of the progressbar + ProgressBar._prototype:increment_filtered(amount,filter) --- Increases the value of the progressbar, if the filter condition is met, does not work with store ProgressBar._prototype:decrement(amount,category) --- Decreases the value of the progressbar - ProgressBar._prototype:add_element(element) --- Adds an element into the list of instances that will are waiting to complete, does not work with store + ProgressBar._prototype:decrement_filtered(amount,filter) --- Decreases the value of the progressbar, if the filter condition is met, does not work with store + ProgressBar._prototype:add_element(element,maximum) --- Adds an element into the list of instances that will are waiting to complete, does not work with store ProgressBar._prototype:reset_element(element) --- Resets an element, or its store, to be back at the start, either 1 or 0 - ProgressBar._prototype:on_complete() --- Triggers when a progress bar element compeltes (hits 0 or 1) - ProgressBar._prototype:on_complete() --- Triggers when a store value completes (hits 0 or 1) - ProgressBar._prototype:event_counter() --- Event handler factory that counts up by 1 every time the event triggeres - ProgressBar._prototype:event_countdown() --- Event handler factory that counts down by 1 every time the event triggeres + ProgressBar._prototype:on_complete(callback) --- Triggers when a progress bar element compeltes (hits 0 or 1) + ProgressBar._prototype:on_complete(callback) --- Triggers when a store value completes (hits 0 or 1) + ProgressBar._prototype:event_counter(filter) --- Event handler factory that counts up by 1 every time the event triggeres, can filter which elements are incremented + ProgressBar._prototype:event_countdown(filter) --- Event handler factory that counts down by 1 every time the event triggeres, can filter which elements are decremented ]] local Toolbar = require 'expcore.gui.toolbar' @@ -227,4 +232,21 @@ Gui.classes.center_frames = CenterFrames CenterFrames._prototype:event_handler(action) --- Creates an event handler that will trigger one of its functions, use with Event.add ]] +local PopupFrames = require 'expcore.gui.popups' +Gui.get_popup_flow = PopupFrames.get_flow +Gui.open_popup = PopupFrames.open +Gui.new_popup = PopupFrames.new_popup +Gui.classes.popup_frames = PopupFrames +--[[ + PopupFrames.get_flow(player) --- Gets the left flow that contains the popup frames + PopupFrames.open(define_name,player,open_time,...) --- Opens a popup for the player, can give the amount of time it is open as well as params for the draw function + + PopupFrames.close_progress --- Progress bar which when depleaded will close the popup frame + PopupFrames.close_button --- A button which can be used to close the gui before the timer runs out + + PopupFrames.new_popup(name) --- Creates a new popup frame define + PopupFrames._prototype:set_default_open_time(amount) --- Sets the default open time for the popup, will be used if non is provided with open + PopupFrames._prototype:open(player,open_time,...) --- Opens this define for a player, can be given open time and any other params for the draw function +]] + return Gui \ No newline at end of file