diff --git a/expcore/Gui/buttons.lua b/expcore/Gui/buttons.lua index 408b307b..a1b4d249 100644 --- a/expcore/Gui/buttons.lua +++ b/expcore/Gui/buttons.lua @@ -29,7 +29,10 @@ function Button.new_button(name) style=mod_gui.button_style, type='button' } - },{__index=Button._prototype}) + },{ + __index=Button._prototype, + __call=function(element) return Button.config[uid]:draw_to(element) end + }) Button.config[uid] = self if name then diff --git a/expcore/Gui/checkboxs.lua b/expcore/Gui/checkboxs.lua index 57493319..49f6e756 100644 --- a/expcore/Gui/checkboxs.lua +++ b/expcore/Gui/checkboxs.lua @@ -7,9 +7,12 @@ local Checkbox = { config={}, clean_names={}, instances={}, + option_mapping={}, + option_categorize={}, _prototype_checkbox=Gui._extend_prototype{}, _prototype_radiobutton=Gui._extend_prototype{} } +setmetatable(Checkbox._prototype_radiobutton,{__index=Checkbox._prototype_checkbox}) Global.register(Checkbox.instances,function(tbl) Checkbox.instances = tbl end) @@ -19,7 +22,7 @@ local function get_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) + return error('Invalid name for checkbox, name not found.',3) or nil end return config end @@ -38,6 +41,15 @@ local function get_instances(checkbox,category) 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() @@ -49,7 +61,10 @@ function Checkbox.new_checkbox(name) type='checkbox', state=false } - },{__index=Checkbox._prototype_checkbox}) + },{ + __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 @@ -70,12 +85,10 @@ function Checkbox.new_checkbox(name) Gui.on_checked_state_changed(self.name,function(event) local element = event.element - if self.store then - if self.categorize then - Store.set_child(self.store,self.categorize(element),element.state) - else - Store.set(self.store,element.state) - end + if self.share_store_location then + set_store(self,self.share_store_location,element,Checkbox.option_mapping[self.share_store_location][element.name]) + elseif self.store then + set_store(self,self.store,element,element.state) elseif self._on_state_change then self._on_state_change(event.player,element) end @@ -105,7 +118,7 @@ function Checkbox._prototype_checkbox:add_store(categorize) self._on_state_change(player,element) end else - table.remove(instances,k) + instances[k] = nil end end end @@ -125,11 +138,7 @@ end function Checkbox._prototype_checkbox:set_store_state(category,state) if not self.store then return end state = not not state - if self.categorize then - return Store.set_child(self.store,category,state) - else - return Store.set(self.store,category) - end + set_store(self,self.store,category,state) end function Checkbox._prototype_checkbox:on_state_change(callback) @@ -140,51 +149,82 @@ function Checkbox._prototype_checkbox:on_state_change(callback) return self end -function Checkbox.reset_radiobutton(element,exclude) - +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) + end + elseif child.children and (type(recursive) == 'number' and recursive > 0 or recursive == true) then + Checkbox.reset_radiobutton(child,exclude,recursive) + end + end + return true end function Checkbox.new_radiobutton(name) + local self = Checkbox.new_checkbox(name) + local uid = self.name + self._draw.type = 'radiobutton' + setmetatable(self,{ + __index=Checkbox._prototype_radiobutton, + __call=function(element) return Checkbox.config[uid]:draw_to(element) end + }) + + return self +end + +function Checkbox.new_share_store(location,callback,categorize) + Store.register(location,function(value,category) + local options = Checkbox.option_mapping[location] + for opt_name,name in pairs(options) do + if Checkbox.config[name] then + get_config(name):set_store_state(category,opt_name == value) + end + end + callback(value,category) + end) + Checkbox.option_categorize[location] = categorize + Checkbox.option_mapping[location] = {} + return location end Checkbox.draw_radiobutton = Checkbox.draw_checkbox -function Checkbox._prototype_radiobutton:draw_to(element) +function Checkbox._prototype_radiobutton:share_store(location,option_name) + self.share_store_location = location + self.option_name = option_name or self.clean_name or self.name -end + Checkbox.option_mapping[location][self.option_name] = self.name + Checkbox.option_mapping[location][self.name] = self.option_name -function Checkbox._prototype_radiobutton:add_store(categorize) - -end - -function Checkbox._prototype_radiobutton:get_store_state(category) - -end - -function Checkbox._prototype_radiobutton:set_store_state(category,value) - -end - -function Checkbox._prototype_radiobutton:enable_single_select(state) - -end - -function Checkbox._prototype_radiobutton:add_option(name) - -end - -function Checkbox._prototype_radiobutton:on_state_change(callback) + self:add_store(Checkbox.option_categorize[location]) + return self end function Checkbox.get_stored_state(name,category) local checkbox = get_config(name) + if checkbox.share_store_location then + if checkbox.categorize then + return Store.get_child(checkbox.share_store_location,category) + else + return Store.get(checkbox.share_store_location) + end + end return checkbox:get_store_state(category) end function Checkbox.set_stored_state(name,category,value) local checkbox = get_config(name) + if checkbox.share_store_location then + set_store(checkbox,checkbox.share_store_location,category,value) + end return checkbox:set_store_state(category,value) end diff --git a/expcore/Gui/test.lua b/expcore/Gui/test.lua index 393b3813..bb7d473c 100644 --- a/expcore/Gui/test.lua +++ b/expcore/Gui/test.lua @@ -6,6 +6,11 @@ local clean_stack_trace = ext_require('modules.commands.interface','clean_stack_ local tests = {} +local function categozie_by_player(element) + local player = Game.get_player_by_index(element.player_index) + return player.name +end + Gui.new_toolbar_button('click-1') :set_authenticator(function(player,button_name) return global.click_one @@ -93,10 +98,7 @@ end) tests['Checkbox store player'] = Gui.new_checkbox('test checkbox store player') :set_caption('Checkbox Store Player') -:add_store(function(element) - local player = Game.get_player_by_index(element.player_index) - return player.name -end) +:add_store(categozie_by_player) :on_state_change(function(player,element) player.print('Checkbox store player: '..tostring(element.state)) end) @@ -109,4 +111,42 @@ tests['Checkbox store force'] = Gui.new_checkbox('test checkbox store force') end) :on_state_change(function(player,element) player.print('Checkbox store force: '..tostring(element.state)) +end) + +tests['Radiobutton local'] = Gui.new_radiobutton('test radiobutton local') +:set_caption('Radiobutton Local') +:on_state_change(function(player,element) + player.print('Radiobutton local: '..tostring(element.state)) +end) + +tests['Radiobutton store player'] = Gui.new_radiobutton('test radiobutton store player') +:set_caption('Radiobutton Store Player') +:add_store(categozie_by_player) +:on_state_change(function(player,element) + player.print('Radiobutton store player: '..tostring(element.state)) +end) + +local test_share = Gui.new_radiobutton_option_set('gui.test.share',function(value,category) + game.print('Radiobutton share: '..category..' is now: '..tostring(value)) +end,categozie_by_player) + +tests['Radiobutton share one'] = Gui.new_radiobutton('test radiobutton share one') +:set_caption('Radiobutton Share One') +:share_store(test_share,'One') +:on_state_change(function(player,element) + player.print('Radiobutton share one: '..tostring(element.state)) +end) + +tests['Radiobutton share two'] = Gui.new_radiobutton('test radiobutton share two') +:set_caption('Radiobutton Share Two') +:share_store(test_share,'Two') +:on_state_change(function(player,element) + player.print('Radiobutton share two: '..tostring(element.state)) +end) + +tests['Radiobutton share three'] = Gui.new_radiobutton('test radiobutton share three') +:set_caption('Radiobutton Share Three') +:share_store(test_share,'Three') +:on_state_change(function(player,element) + player.print('Radiobutton share three: '..tostring(element.state)) end) \ No newline at end of file diff --git a/expcore/gui.lua b/expcore/gui.lua index 0c33e34b..e2b5ac24 100644 --- a/expcore/gui.lua +++ b/expcore/gui.lua @@ -12,6 +12,8 @@ Gui.structure.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_share_store Gui.inputs.checkboxs = Checkboxs return Gui \ No newline at end of file diff --git a/expcore/store.lua b/expcore/store.lua index f9e31f30..06b4d6a6 100644 --- a/expcore/store.lua +++ b/expcore/store.lua @@ -90,6 +90,13 @@ Global.register(Store.data,function(tbl) Store.data = tbl end) +--- Check for if a lcoation is registered +-- @tparam location string the location to test for +-- @treturn boolean true if registered +function Store.is_registered(location) + return not not Store.callbacks[location] +end + --- Registers a new location with an update callback which is triggered when the value updates -- @tparam location string a unique string that points to the data, string used rather than token to allow migration -- @tparam callback function this callback will be called when the stored value is set to a new value @@ -109,6 +116,8 @@ function Store.register(location,callback,start_value) Store.data[location] = start_value Store.callbacks[location] = callback + + return location end --- Registers a new cross server synced location with an update callback, and external script is required for cross server