diff --git a/expcore/Gui/buttons.lua b/expcore/Gui/buttons.lua index 7c945ea9..f942af47 100644 --- a/expcore/Gui/buttons.lua +++ b/expcore/Gui/buttons.lua @@ -12,37 +12,14 @@ local Button = { } } -local function get_config(name) - local config = Button.config[name] - if not config and Button.clean_names[name] then - return Button.config[Button.clean_names[name]] - elseif not config then - return error('Invalid name for checkbox, name not found.',3) - end - return config -end - function Button.new_button(name) - local uid = Gui.uid_name() - local self = setmetatable({ - name=uid, - clean_name=name, - events={}, - draw_data={ - name=uid, - style=mod_gui.button_style, - type='button' - } - },{ - __index=Button._prototype, - __call=function(element) return Button.config[uid]:draw_to(element) end - }) - Button.config[uid] = self + local self = Gui._new_define(Button._prototype) + self.draw_data.type = 'button' + self.draw_data.style = mod_gui.button_style if name then - Button.clean_names[uid]=name - Button.clean_names[name]=uid + self:debug_name(name) end Gui.on_click(self.name,function(event) @@ -75,11 +52,6 @@ function Button.new_button(name) return self end -function Button.draw_button(name,element) - local config = get_config(name) - return config:draw_to(element) -end - function Button._prototype:set_sprites(sprite,hovered_sprite,clicked_sprite) self.draw_data.type = 'sprite-button' self.draw_data.sprite = sprite diff --git a/expcore/Gui/checkboxs.lua b/expcore/Gui/checkboxs.lua index be939757..0f45e48c 100644 --- a/expcore/Gui/checkboxs.lua +++ b/expcore/Gui/checkboxs.lua @@ -1,130 +1,62 @@ local Gui = require './core' local Store = require 'expcore.store' -local Global = require 'utils.global' local Game = require 'utils.game' +local function store_state(self,element,value) + element.state = value + if self.events.on_state_change then + local player = Game.get_player_by_index(element.player_index) + self.events.on_state_change(player,element) + end +end + local Checkbox = { - config={}, - clean_names={}, - instances={}, option_sets={}, option_categorize={}, _prototype_checkbox=Gui._extend_prototype{ - on_state_change = Gui._new_event_adder('on_state_change') + on_state_change = Gui._new_event_adder('on_state_change'), + add_store = Gui._new_store_adder(store_state) }, _prototype_radiobutton=Gui._extend_prototype{ - on_state_change = Gui._new_event_adder('on_state_change') + on_state_change = Gui._new_event_adder('on_state_change'), + add_store = Gui._new_store_adder(store_state) } } setmetatable(Checkbox._prototype_radiobutton,{__index=Checkbox._prototype_checkbox}) -Global.register(Checkbox.instances,function(tbl) - Checkbox.instances = tbl -end) - -local function get_config(name) - local config = Checkbox.config[name] - if not config and Checkbox.clean_names[name] then - return Checkbox.config[Checkbox.clean_names[name]] - elseif not config then - return error('Invalid name for checkbox, name not found.',3) or nil - end - return config -end - -local function get_instances(checkbox,category) - if not Checkbox.instances[checkbox.name] then return end - local instances = Checkbox.instances[checkbox.name] - if checkbox.categorize then - if not instances[category] then instances[category] = {} end - return instances[category] - end - return instances -end - -local function set_store(config,location,element,value) - if config.categorize then - local child = type(element) == 'string' and element or config.categorize(element) - Store.set_child(location,child,value) - else - Store.set(location,value) - end -end function Checkbox.new_checkbox(name) - local uid = Gui.uid_name() - local self = setmetatable({ - name=uid, - clean_name=name, - events={}, - draw_data={ - name=uid, - type='checkbox', - state=false - } - },{ - __index=Checkbox._prototype_checkbox, - __call=function(element) return Checkbox.config[uid]:draw_to(element) end - }) - - self._post_draw = function(element) - local category = self.categorize and self.categorize(element) or nil - local instances = get_instances(self,category) - if instances then - table.insert(instances,element) - end - local state = self:get_store_state(category) - if state then element.state = true end - end - - Checkbox.config[uid] = self + local self = Gui._new_define(Checkbox._prototype_checkbox) + self.draw_data.type = 'checkbox' + self.draw_data.state = false if name then - Checkbox.clean_names[uid]=name - Checkbox.clean_names[name]=uid + 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 state = self:get_store(category,true) + if state then element.state = true end + end end Gui.on_checked_state_changed(self.name,function(event) local element = event.element + if self.option_set then - set_store(self,self.option_set,element,Checkbox.option_sets[self.option_set][element.name]) + local value = Checkbox.option_sets[self.option_set][element.name] + local category = self.categorize and self.categorize(element) or value + self:set_store(category,value) + elseif self.store then - set_store(self,self.store,element,element.state) + local value = element.state + local category = self.categorize and self.categorize(element) or value + self:set_store(category,value) + elseif self.events.on_state_change then self.events.on_state_change(event.player,element) - end - end) - - return Checkbox.config[uid] -end - -function Checkbox.draw_checkbox(name,element) - local config = get_config(name) - return config:draw_to(element) -end - -function Checkbox._prototype_checkbox:add_store(categorize) - if self.store then return end - - self.store = Store.uid_location() - self.categorize = categorize - Checkbox.instances[self.name]={} - - Store.register(self.store,function(value,category) - local instances = get_instances(self,category) - if instances then - - for k,element in pairs(instances) do - if element and element.valid then - element.state = value - if self.events.on_state_change then - local player = Game.get_player_by_index(element.player_index) - self.events.on_state_change(player,element) - end - else - instances[k] = nil - end - end end end) @@ -132,30 +64,19 @@ function Checkbox._prototype_checkbox:add_store(categorize) return self end -function Checkbox._prototype_checkbox:get_store_state(category) - if not self.store then return end - if self.categorize then - return Store.get_child(self.store,category) - else - return Store.get(self.store) - end -end - -function Checkbox._prototype_checkbox:set_store_state(category,state) - if not self.store then return end - set_store(self,self.store,category,not not state) -end - function Checkbox.reset_radiobutton(element,exclude,recursive) if not element or not element.valid then return end exclude = type(exclude) == 'table' and exclude or exclude ~= nil and {[exclude]=true} or {} for _,child in pairs(element.children) do if child and child.valid and child.type == 'radiobutton' then - child.state = exclude[child.name] or false - local config = Checkbox.config[child.name] - if config then - set_store(config,config.store,child,exclude[child.name] or false) + local state = exclude[child.name] or false + local define = Gui.defines[child.name] + if define then + local category = define.categorize and define.categorize(child) or state + define:set_store(category,state) + else + child.state = state end elseif child.children and (type(recursive) == 'number' and recursive > 0 or recursive == true) then Checkbox.reset_radiobutton(child,exclude,recursive) @@ -167,19 +88,14 @@ end function Checkbox.new_radiobutton(name) local self = Checkbox.new_checkbox(name) - local uid = self.name self.draw_data.type = 'radiobutton' - setmetatable(self,{ - __index=Checkbox._prototype_radiobutton, - __call=function(element) return Checkbox.config[uid]:draw_to(element) end - }) + local mt = getmetatable(self) + mt.__index = Checkbox._prototype_radiobutton return self end -Checkbox.draw_radiobutton = Checkbox.draw_checkbox - function Checkbox._prototype_radiobutton:add_as_option(option_set,option_name) self.option_set = option_set self.option_name = option_name or self.clean_name or self.name @@ -192,13 +108,37 @@ function Checkbox._prototype_radiobutton:add_as_option(option_set,option_name) return self end +function Checkbox._prototype_radiobutton:get_store(category,internal) + if not self.store then return end + local location = not internal and self.option_set or self.store + + if self.categorize then + return Store.get_child(location,category) + else + return Store.get(location) + end +end + +function Checkbox._prototype_radiobutton:set_store(category,value,internal) + if not self.store then return end + local location = not internal and self.option_set or self.store + + if self.categorize then + return Store.set_child(location,category,value) + else + return Store.set(location,category) + end +end + function Checkbox.new_option_set(name,callback,categorize) Store.register(name,function(value,category) local options = Checkbox.option_sets[name] - for opt_name,config_name in pairs(options) do - if Checkbox.config[config_name] then - get_config(config_name):set_store_state(category,opt_name == value) + for opt_name,define_name in pairs(options) do + if Gui.defines[define_name] then + local define = Gui.get_define(define_name) + local state = opt_name == value + define:set_store(category,state,true) end end callback(value,category) @@ -210,24 +150,4 @@ function Checkbox.new_option_set(name,callback,categorize) return name end -function Checkbox.get_stored_state(name,category) - local config = get_config(name) - - if config.option_set then - if config.categorize then - return Store.get_child(config.option_set,category) - else - return Store.get(config.option_set) - end - end - - return config:get_store_state(category) -end - -function Checkbox.set_stored_state(name,category,value) - local config = get_config(name) - local location = config.option_set or config.store - set_store(config,location,category,value) -end - return Checkbox \ No newline at end of file diff --git a/expcore/Gui/core.lua b/expcore/Gui/core.lua index 02a038d9..73612f02 100644 --- a/expcore/Gui/core.lua +++ b/expcore/Gui/core.lua @@ -1,10 +1,38 @@ local Gui = require 'utils.gui' local Game = require 'utils.game' +local Global = require 'utils.global' +local Store = require 'expcore.store' + +Gui._prototype = {} -- Stores the base prototype of all gui defines +Gui.classes = {} -- Stores the class types of gui defines +Gui.defines = {} -- Stores the indivdual gui element definations +Gui.names = {} -- Stores debug names to link to gui uids +Gui.instances = {} -- Stores runtime data of all active instances of each define +Global.register(Gui.instances,function(tbl) + Gui.instances = tbl +end) + + +function Gui.get_define(name,internal) + local define = Gui.defines[name] + if not define and Gui.names[name] then + 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 + end + return define +end + +function Gui.get_instances(self,category) + if not Gui.instances[self.name] then return end + local instances = Gui.instances[self.name] + if self.categorize then + if not instances[category] then instances[category] = {} end + return instances[category] + end + return instances +end -Gui._prototype = {} -Gui.inputs = {} -Gui.structure = {} -Gui.outputs = {} function Gui._extend_prototype(tbl) for k,v in pairs(Gui._prototype) do @@ -23,11 +51,63 @@ function Gui._new_event_adder(name) end end +function Gui._new_store_adder(callback) + return function(self,categorize) + if self.store then return end + + self.store = Store.uid_location() + self.categorize = categorize + Gui.instances[self.name]={} + + Store.register(self.store,function(value,category) + 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 + + end + end) + + return self + end +end + +function Gui._new_define(prototype) + local uid = Gui.uid_name() + local define = setmetatable({ + name=uid, + events={}, + draw_data={ + name=uid + } + },{ + __index=prototype, + __call=function(self,element) + return self:draw_to(element) + end + }) + Gui.defines[define.name] = define + return define +end + --- Gets the uid for the config function Gui._prototype:uid() return self.name end +--- Sets an alias to the uid +function Gui._prototype:debug_name(name) + self.debug_name = name + Gui.names[name] = self.name + return self +end + --- Sets the caption for the element config function Gui._prototype:set_caption(caption) self.draw_data.caption = caption @@ -62,15 +142,63 @@ end function Gui._prototype:draw_to(element) if element[self.name] then return end local player = Game.get_player_by_index(element.player_index) + if self.pre_authenticator then if not self.pre_authenticator(player,self.clean_name or self.name) then return end end - local _element = element.add(self.draw_data) + + local new_element = element.add(self.draw_data) + if self.post_authenticator then - _element.enabled = not not self.post_authenticator(player,self.clean_name or self.name) + new_element.enabled = self.post_authenticator(player,self.clean_name or self.name) end - if self._post_draw then self._post_draw(_element) end - return _element + + 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 + end + + if self.post_draw then self.post_draw(new_element) end + + return new_element +end + +--- Gets the value in this elements store +function Gui._prototype:get_store(category) + if not self.store then return end + if self.categorize then + return Store.get_child(self.store,category) + else + return Store.get(self.store) + end +end + +--- Sets the value in this elements store +function Gui._prototype:set_store(category,value) + if not self.store then return end + if self.categorize then + return Store.set_child(self.store,category,value) + else + return Store.set(self.store,category) + end +end + +function Gui.get_store(name,category) + local define = Gui.get_define(name,true) + return define:get_store(category) +end + +function Gui.set_store(name,category,value) + local define = Gui.get_define(name,true) + return define:get_store(category,value) +end + +function Gui.draw(name,element) + local define = Gui.get_define(name,true) + return define:draw_to(element) end function Gui.toggle_enable(element) diff --git a/expcore/gui.lua b/expcore/gui.lua index 151ce46f..b9a50b1a 100644 --- a/expcore/gui.lua +++ b/expcore/gui.lua @@ -1,19 +1,20 @@ -- This file is used to require all the different elements of the gui module local Gui = require('./gui/core') -local Buttons = require('./gui/buttons') -Gui.new_button = Buttons.new_button -Gui.inputs.buttons = Buttons +local Button = require('./gui/buttons') +Gui.new_button = Button.new_button +Gui.classes.button = Button local Toolbar = require('./gui/toolbar') Gui.new_toolbar_button = Toolbar.new_button Gui.add_button_to_toolbar = Toolbar.add_button -Gui.structure.toolbar = Toolbar +Gui.update_toolbar = Toolbar.update +Gui.classes.toolbar = Toolbar -local Checkboxs = require('./gui/checkboxs') -Gui.new_checkbox = Checkboxs.new_checkbox -Gui.new_radiobutton = Checkboxs.new_radiobutton -Gui.new_radiobutton_option_set = Checkboxs.new_option_set -Gui.inputs.checkboxs = Checkboxs +local Checkbox = require('./gui/checkboxs') +Gui.new_checkbox = Checkbox.new_checkbox +Gui.new_radiobutton = Checkbox.new_radiobutton +Gui.new_radiobutton_option_set = Checkbox.new_option_set +Gui.classes.checkbox = Checkbox return Gui \ No newline at end of file