From 5c43c5f8549120cf2faa748e5e6793a22f1429bd Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Fri, 10 May 2019 19:00:06 +0100 Subject: [PATCH] Added checkboxes --- expcore/Gui/buttons.lua | 108 +++++++++------------- expcore/Gui/checkboxs.lua | 182 ++++++++++++++++++++++++++++++++++++++ expcore/Gui/core.lua | 36 +++++++- expcore/store.lua | 8 +- 4 files changed, 264 insertions(+), 70 deletions(-) create mode 100644 expcore/Gui/checkboxs.lua diff --git a/expcore/Gui/buttons.lua b/expcore/Gui/buttons.lua index 178f3b98..6dff22e2 100644 --- a/expcore/Gui/buttons.lua +++ b/expcore/Gui/buttons.lua @@ -19,17 +19,50 @@ local function get_config(name) end function Button.new_button(name) + local uid = Gui.uid_name() - Button.config[uid] = setmetatable({ + local self = setmetatable({ name=uid, - clean_name=name, - style=mod_gui.button_style, - type='button' + clean_name=name },{__index=Button._prototype}) + + self._draw.name = uid + self._draw.style = mod_gui.button_style + self._draw.type = 'button' + Button.config[uid] = self + if name then Button.clean_names[uid]=name Button.clean_names[name]=uid end + + Gui.on_click(self.name,function(event) + local mosue_button = event.button + local keys = {alt=event.alt,control=event.control,shift=event.shift} + event.keys = keys + + if self.authenticator then + if not self.authenticator(event.player,self.clean_name or self.name) then return end + end + + if mosue_button == defines.mouse_button_type.left and self._on_left_click then + self.on_left_click(event.player,event.element,event) + elseif mosue_button == defines.mouse_button_type.right and self._on_right_click then + self.on_right_click(event.player,event.element,event) + end + + if self.mouse_button_filter and not self.mouse_button_filter[mosue_button] then return end + if self.key_button_filter then + for key,state in pairs(self.key_button_filter) do + if state and not keys[key] then return end + end + end + + if self._on_click then + self._on_click(event.player,event.element,event) + end + end) + return Button.config[uid] end @@ -38,29 +71,11 @@ function Button.draw_button(name,element) return button:draw_to(element) end -function Button._prototype:draw_to(element) - if element.children[self.name] then return end - local draw = table.deep_copy(self) - draw.authenticator = nil - draw.clean_name = nil - draw.raw_mouse_button_filter = nil - draw.key_button_filter = nil - draw._on_click = nil - draw._on_left_click = nil - draw._on_right_click = nil - draw.has_handler = nil - local self_element = element.add(draw) - if self.authenticator then - self_element.enabled = not not self.authenticator(element.player,self.clean_name or self.name) - end - return self_element -end - function Button._prototype:set_sprites(sprite,hovered_sprite,clicked_sprite) - self.type = 'sprite-button' - self.sprite = sprite - self.hovered_sprite = hovered_sprite - self.clicked_sprite = clicked_sprite + self._draw.type = 'sprite-button' + self._draw.sprite = sprite + self._draw.hovered_sprite = hovered_sprite + self._draw.clicked_sprite = clicked_sprite return self end @@ -77,7 +92,6 @@ function Button._prototype:set_click_filter(filter,...) end end self.mouse_button_filter = filter - self.raw_mouse_button_filter = filter return self end @@ -92,20 +106,11 @@ function Button._prototype:set_key_filter(filter,...) return self end -function Button._prototype:set_authenticator(callback) - if type(callback) ~= 'function' then - return error('Authenicater callback must be a function') - end - self.authenticator = callback - return self -end - function Button._prototype:on_click(callback) if type(callback) ~= 'function' then return error('Event callback must be a function') end self._on_click = callback - self:_add_handler() return self end @@ -114,7 +119,6 @@ function Button._prototype:on_left_click(callback) return error('Event callback must be a function') end self._on_left_click = callback - self:_add_handler() return self end @@ -123,37 +127,7 @@ function Button._prototype:on_right_click(callback) return error('Event callback must be a function') end self._on_right_click = callback - self:_add_handler() return self end -function Button._prototype:_add_handler() - if self.has_handler then return end - self.has_handler = true - Gui.on_click(self.name,function(event) - local mosue_button = event.button - local keys = {alt=event.alt,control=event.control,shift=event.shift} - event.keys = keys - - if self.authenticator then - if not self.authenticator(event.player,self.clean_name or self.name) then return end - end - - if mosue_button == defines.mouse_button_type.left and self._on_left_click then - self.on_left_click(event.player,event.element,event) - elseif mosue_button == defines.mouse_button_type.right and self._on_right_click then - self.on_right_click(event.player,event.element,event) - end - - if self.raw_mouse_button_filter and not self.raw_mouse_button_filter[mosue_button] then return end - if self.key_button_filter then - for key,state in pairs(self.key_button_filter) do - if state and not keys[key] then return end - end - end - - self._on_click(event.player,event.element,event) - end) -end - return Button \ No newline at end of file diff --git a/expcore/Gui/checkboxs.lua b/expcore/Gui/checkboxs.lua new file mode 100644 index 00000000..3ef2a098 --- /dev/null +++ b/expcore/Gui/checkboxs.lua @@ -0,0 +1,182 @@ +local Gui = require './core' +local Store = require 'expcore.store' +local Global = require 'utils.global' +local Game = require 'utils.game' + +local Checkbox = { + config={}, + clean_names={}, + instances={}, + _prototype_checkbox=Gui._extend_prototype{}, + _prototype_radiobutton=Gui._extend_prototype{} +} +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) + end + return config +end + +local function get_store_location(checkbox) + return 'gui.inputs.checkbox.'..(checkbox.clean_name or checkbox.name) +end + +local function get_instances(checkbox,category) + if not Checkbox.instances[checkbox.name] then return end + local instances = Checkbox.instances + if checkbox.categorize then + instances = instances[category] + end + return instances +end + +function Checkbox.new_checkbox(name) + + local uid = Gui.uid_name() + local self = setmetatable({ + name=uid, + clean_name=name, + },{__index=Checkbox._prototype_checkbox}) + self._draw.name = uid + self._draw.type = 'checkbox' + + 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 + end + + Checkbox.config[uid] = self + + if name then + Checkbox.clean_names[uid]=name + Checkbox.clean_names[name]=uid + end + + Gui.on_checked_state_changed(self.name,function(event) + local element = event.element + if self.store then + if self.categorize then + Store.set_chlid(self.store,self.categorize(element),element.state) + else + Store.set(self.store,element.state) + end + elseif self._on_state_change then + self._on_state_change(event.player,element) + end + end) + + return Checkbox.config[uid] +end + +function Checkbox.draw_checkbox(name,element) + local checkbox = get_config(name) + return checkbox:draw_to(element) +end + +function Checkbox._prototype_checkbox:add_store(categorize) + if self.store then return end + self.store = get_store_location(self) + self.categorize = categorize + 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.valid then + element.state = value + if self._on_state_change then + local player = Game.get_player_by_index(element.player_index) + self._on_state_change(player,element) + end + else + table.remove(instances,k) + end + end + end + end) + 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_chlid(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 + state = not not state + if self.categorize then + return Store.set_chlid(self.store,category,state) + else + return Store.set(self.store,state) + end +end + +function Checkbox._prototype_checkbox:on_state_change(callback) + if type(callback) ~= 'function' then + return error('Event callback must be a function') + end + self._on_state_change = callback + return self +end + +function Checkbox.reset_radiobutton(element,exclude) + +end + +function Checkbox.new_radiobutton(name) + +end + +Checkbox.draw_radiobutton = Checkbox.draw_checkbox + +function Checkbox._prototype_radiobutton:draw_to(element) + +end + +function Checkbox._prototype_radiobutton:add_store(categorize) + +end + +function Checkbox._prototype_radiobutton:get_store_value(category) + +end + +function Checkbox._prototype_radiobutton:set_store_value(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) + +end + +function Checkbox.get_stored_value(name,category) + +end + +function Checkbox.set_stored_value(name,category,value) + +end + +return Checkbox \ No newline at end of file diff --git a/expcore/Gui/core.lua b/expcore/Gui/core.lua index 2ff6bca3..0a1a21a8 100644 --- a/expcore/Gui/core.lua +++ b/expcore/Gui/core.lua @@ -1,13 +1,13 @@ local Gui = require 'utils.gui' -Gui._prototype = {} +Gui._prototype = {_draw={}} Gui.inputs = {} Gui.structure = {} Gui.outputs = {} function Gui._extend_prototype(tbl) for k,v in pairs(Gui._prototype) do - if not tbl[k] then tbl[k] = v end + if not tbl[k] then tbl[k] = table.deep_copy(v) end end return tbl end @@ -24,6 +24,38 @@ function Gui._prototype:set_tooltip(tooltip) return self end +--- Sets an authenticator that blocks the draw function if check fails +function Gui._prototype:set_pre_authenticator(callback) + if type(callback) ~= 'function' then + return error('Pre authenticator callback must be a function') + end + self.pre_authenticator = callback + return self +end + +--- Sets an authenticator that disables the element if check fails +function Gui._prototype:set_authenticator(callback) + if type(callback) ~= 'function' then + return error('Authenicater callback must be a function') + end + self.authenticator = callback + return self +end + +--- Draws the element using what is in the _draw table, allows use of authenticator if present +function Gui._prototype:draw_to(element) + if element.children[self.name] then return end + if self.pre_authenticator then + if not self.pre_authenticator(element.player,self.clean_name or self.name) then return end + end + local _element = element.add(self._draw) + if self.authenticator then + _element.enabled = not not self.authenticator(element.player,self.clean_name or self.name) + end + if self._post_draw then self._post_draw(_element) end + return _element +end + function Gui.toggle_enable(element) if not element or not element.valid then return end if not element.enabled then diff --git a/expcore/store.lua b/expcore/store.lua index 3469156b..822e3a65 100644 --- a/expcore/store.lua +++ b/expcore/store.lua @@ -78,7 +78,7 @@ local Global = require 'util.global' local Event = require 'util.event' -local write_json,table_keys = ext_require('expcore.common','write_json','table_keys') +local write_json = ext_require('expcore.common','write_json','table_keys') local Store = { data={}, @@ -167,6 +167,7 @@ end --- Sets the value at a location, this location must be registered, if server synced it will emit the change to file -- @tparam location string the location to set the data to -- @tparam value any the new value to set at the location, value may be reverted if there is a watch callback +-- @treturn boolean true if it was successful function Store.set(location,value) if not Store.callbacks[location] and not no_error then return error('Location is not registered', 2) @@ -181,6 +182,8 @@ function Store.set(location,value) value=value }) end + + return true end --- Gets all non nil children at a location, children can be added and removed during runtime @@ -217,6 +220,7 @@ end -- @tparam location string the location of which the child is located -- @tparam child string the child element to set the value of -- @tparam value any the value to set at this location +-- @treturn boolean true if it was successful function Store.set_child(location,child,value) local store = Store.get(location) @@ -238,6 +242,8 @@ function Store.set_child(location,child,value) value=value }) end + + return true end -- Event handler for the watcher callbacks