Mercurial > wow > reaction
changeset 79:a45255f5d0c2
- Converted State options to use static options table + metatable handler
- Fixed bug with FixAll()
- Added external property handler registration
- Removed pages handler (to be migrated to ReAction_Action)
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Tue, 24 Jun 2008 23:39:43 +0000 |
parents | 502cdb5666e2 |
children | 42ec2938d65a |
files | State.lua |
diffstat | 1 files changed, 553 insertions(+), 470 deletions(-) [+] |
line wrap: on
line diff
--- a/State.lua Tue Jun 24 00:10:33 2008 +0000 +++ b/State.lua Tue Jun 24 23:39:43 2008 +0000 @@ -53,7 +53,7 @@ end -local InitRules, ApplyStates, SetProperty, GetProperty +local InitRules, ApplyStates, SetProperty, GetProperty, RegisterProperty -- PRIVATE -- do @@ -142,7 +142,7 @@ bar:SetStateAttribute(format("headofs%s",ofskeys[ckey]), map, default) end - -- the name of the function maps to the name of the config element + -- the table key name for each function maps to the name of the config element local propertyFuncs = { hide = function( bar, states ) local hs = { } @@ -154,16 +154,6 @@ bar:SetStateAttribute("hidestates", nil, table.concat(hs,","), true) -- pass to buttons end, - page = function( bar, states ) - local map = { } - for state, config in pairs(states) do - if config.page then - map[state] = format("page%d",config.page) - end - end - bar:SetStateAttribute("statebutton", map) - end, - keybindstate = function( bar, states ) local map = { } for state, config in pairs(states) do @@ -216,6 +206,16 @@ end end + function RegisterProperty( propname, f ) + propertyFuncs[propname] = f + for bar in ReAction:IterateBars() do + local states = tfetch(module.db.profile.bars, bar:GetName(), "states") + if states then + f(bar,states) + end + end + end + -- @@ -379,19 +379,19 @@ end function module:OnConfigModeChanged(event, mode) - -- TODO: unregister all state drivers (temporarily) and hidestates + -- nothing to do (yet) end -- Options -- -local CreateBarOptions +local CreateBarOptions, RegisterPropertyOptions do + local playerClass = select(2, UnitClass("player")) local function ClassCheck(...) for i = 1, select('#',...) do - local _, c = UnitClass("player") - if c == select(i,...) then + if playerClass == select(i,...) then return false end end @@ -442,465 +442,532 @@ end end + local stateOptions = { + ordering = { + name = L["Info"], + order = 1, + type = "group", + args = { + delete = { + name = L["Delete this State"], + order = -1, + type = "execute", + func = "DeleteState", + }, + rename = { + name = L["Name"], + order = 1, + type = "input", + get = "GetName", + set = "SetStateName", + pattern = "^%w*$", + usage = L["State names must be alphanumeric without spaces"], + }, + ordering = { + name = L["Evaluation Order"], + desc = L["State transitions are evaluated in the order listed:\nMove a state up or down to change the order"], + order = 2, + type = "group", + inline = true, + args = { + up = { + name = L["Up"], + order = 1, + type = "execute", + width = "half", + func = "MoveStateUp", + }, + down = { + name = L["Down"], + order = 2, + type = "execute", + width = "half", + func = "MoveStateDown", + } + } + } + } + }, + properties = { + name = L["Properties"], + order = 2, + type = "group", + args = { + desc = { + name = L["Set the properties for the bar when in this state"], + order = 1, + type = "description" + }, + hide = { + name = L["Hide Bar"], + order = 91, + type = "toggle", + set = "SetProp", + get = "GetProp", + }, + keybindstate = { + name = L["Override Keybinds"], + desc = L["Set this state to maintain its own set of keybinds which override the defaults when active"], + order = 92, + type = "toggle", + set = "SetProp", + get = "GetProp", + }, + position = { + name = L["Position"], + order = 93, + type = "group", + inline = true, + args = { + enableAnchor = { + name = L["Set New Position"], + order = 1, + type = "toggle", + set = "SetProp", + get = "GetProp", + }, + anchorPoint = { + name = L["Point"], + order = 2, + type = "select", + values = pointTable, + set = "SetAnchorPointProp", + get = "GetAnchorPointProp", + disabled = "GetAnchorDisabled", + hidden = "GetAnchorDisabled", + }, + anchorRelPoint = { + name = L["Relative Point"], + order = 3, + type = "select", + values = pointTable, + set = "SetAnchorPointProp", + get = "GetAnchorPointProp", + disabled = "GetAnchorDisabled", + hidden = "GetAnchorDisabled", + }, + anchorX = { + name = L["X Offset"], + order = 4, + type = "range", + min = -100, + max = 100, + step = 1, + set = "SetProp", + get = "GetProp", + disabled = "GetAnchorDisabled", + hidden = "GetAnchorDisabled", + }, + anchorY = { + name = L["Y Offset"], + order = 5, + type = "range", + min = -100, + max = 100, + step = 1, + set = "SetProp", + get = "GetProp", + disabled = "GetAnchorDisabled", + hidden = "GetAnchorDisabled", + }, + }, + }, + scale = { + name = L["Scale"], + order = 94, + type = "group", + inline = true, + args = { + enableScale = { + name = L["Set New Scale"], + order = 1, + type = "toggle", + set = "SetProp", + get = "GetProp", + }, + scale = { + name = L["Scale"], + order = 2, + type = "range", + min = 0.1, + max = 2.5, + step = 0.05, + isPercent = true, + set = "SetProp", + get = "GetProp", + disabled = "GetScaleDisabled", + hidden = "GetScaleDisabled", + }, + }, + }, + }, + plugins = { } + }, + rules = { + name = L["Rule"], + order = 3, + type = "group", + args = { + mode = { + name = L["Select this state"], + order = 2, + type = "select", + style = "radio", + values = { + default = L["by default"], + any = L["when ANY of these"], + all = L["when ALL of these"], + custom = L["via custom rule"], + keybind = L["via keybinding"], + }, + set = "SetType", + get = "GetType", + }, + clear = { + name = L["Clear All"], + order = 3, + type = "execute", + hidden = "GetClearAllDisabled", + disabled = "GetClearAllDisabled", + func = "ClearAllConditions", + }, + inputs = { + name = L["Conditions"], + order = 4, + type = "multiselect", + hidden = "GetConditionsDisabled", + disabled = "GetConditionsDisabled", + values = ruleSelect, + set = "SetCondition", + get = "GetCondition", + }, + custom = { + name = L["Custom Rule"], + order = 5, + type = "input", + multiline = true, + hidden = "GetCustomDisabled", + disabled = "GetCustomDisabled", + desc = L["Syntax like macro rules: see preset rules for examples"], + set = "SetCustomRule", + get = "GetCustomRule", + validate = "ValidateCustomRule", + }, + keybind = { + name = L["Keybinding"], + order = 6, + inline = true, + hidden = "GetKeybindDisabled", + disabled = "GetKeybindDisabled", + type = "group", + args = { + desc = { + name = L["Invoking a state keybind toggles an override of all other transition rules."], + order = 1, + type = "description", + }, + keybind = { + name = L["State Hotkey"], + desc = L["Define an override toggle keybind"], + order = 2, + type = "keybinding", + set = "SetKeybind", + get = "GetKeybind", + }, + }, + }, + }, + }, + } + + local StateHandler = { } + + function StateHandler:New( bar, opts ) + local self = setmetatable({ bar = bar }, { __index = StateHandler }) + + function self:GetName() + return opts.name + end + + function self:SetName(name) + opts.name = name + end + + function self:GetOrder() + return opts.order + end + + -- get reference to states table: even if the bar + -- name changes the states table ref won't + self.states = tbuild(module.db.profile.bars, bar:GetName(), "states") + + tbuild(self.states, opts.name) + + opts.order = self:GetRule("order") + if opts.order == nil then + -- add after the highest + opts.order = 100 + for _, state in pairs(self.states) do + local x = tonumber(tfetch(state, "rule", "order")) + if x and x >= opts.order then + opts.order = x + 1 + end + end + self:SetRule("order",opts.order) + end + + return self + end + + -- helper methods + + function StateHandler:SetRule( key, value, ... ) + tbuild(self.states, self:GetName(), "rule", ...)[key] = value + end + + function StateHandler:GetRule( ... ) + return tfetch(self.states, self:GetName(), "rule", ...) + end + + function StateHandler:FixAll( setkey ) + -- if multiple selections in the same group are chosen when 'all' is selected, + -- keep only one of them. If changing the mode, the first in the fields list will + -- be chosen arbitrarily. Otherwise, if selecting a new checkbox from the field-set, + -- it will be retained. + local notified = false + if self:GetRule("type") == "all" then + for _, c in ipairs(rules) do + local rule, hidden, fields = unpack(c) + local once = false + if setkey then + for idx, field in ipairs(fields) do + if next(field) == setkey then + once = true + end + end + end + for idx, field in ipairs(fields) do + local key = next(field) + if self:GetRule("values",key) then + if once and key ~= setkey then + self:SetRule(key,false,"values") + if not setkey and not notified then + ReAction:UserError(L["Warning: one or more incompatible rules were turned off"]) + notified = true + end + end + once = true + end + end + end + end + end + + function StateHandler:GetNeighbors() + local before, after + for k, v in pairs(self.states) do + local o = tonumber(tfetch(v, "rule", "order")) + if o and k ~= self:GetName() then + local obefore = tfetch(self.states,before,"rule","order") + local oafter = tfetch(self.states,after,"rule","order") + if o < self:GetOrder() and (not obefore or obefore < o) then + before = k + end + if o > self:GetOrder() and (not oafter or oafter > o) then + after = k + end + end + end + return before, after + end + + function StateHandler:SwapOrder( a, b ) + -- do options table + local args = optionMap[self.bar].args + args[a].order, args[b].order = args[b].order, args[a].order + -- do profile + a = tbuild(self.states, a, "rule") + b = tbuild(self.states, b, "rule") + a.order, b.order = b.order, a.order + end + + -- handler methods + + function StateHandler:GetProp( info ) + -- gets property of the same name as the options arg + return GetProperty(self.bar, self:GetName(), info[#info]) + end + + function StateHandler:SetProp( info, value ) + -- sets property of the same name as the options arg + SetProperty(self.bar, self:GetName(), info[#info], value) + end + + function StateHandler:DeleteState() + if self.states[self:GetName()] then + self.states[self:GetName()] = nil + ApplyStates(self.bar) + end + optionMap[self.bar].args[self:GetName()] = nil + end + + function StateHandler:SetStateName(info, value) + -- check for existing state name + if self.states[value] then + ReAction:UserError(format(L["State named '%s' already exists"],value)) + return + end + local args = optionMap[self.bar].args + local name = self:GetName() + self.states[value], args[value], self.states[name], args[name] = self.states[name], args[name], nil, nil + self:SetName(value) + ApplyStates(self.bar) + end + + function StateHandler:MoveStateUp() + local before, after = self:GetNeighbors() + if before then + self:SwapOrder(before, self:GetName()) + ApplyStates(self.bar) + end + end + + function StateHandler:MoveStateDown() + local before, after = self:GetNeighbors() + if after then + self:SwapOrder(self:GetName(), after) + ApplyStates(self.bar) + end + end + + function StateHandler:GetAnchorDisabled() + return not GetProperty(self.bar, self:GetName(), "enableAnchor") + end + + function StateHandler:SetAnchorPointProp(info, value) + self:SetProp(info, value ~= "NONE" and value or nil) + end + + function StateHandler:GetAnchorPointProp(info) + return self:GetProp(info) or "NONE" + end + + function StateHandler:GetScaleDisabled() + return not GetProperty(self.bar, self:GetName(), "enableScale") + end + + function StateHandler:SetType(info, value) + self:SetRule("type", value) + self:FixAll() + ApplyStates(self.bar) + end + + function StateHandler:GetType() + return self:GetRule("type") + end + + function StateHandler:GetClearAllDisabled() + local t = self:GetRule("type") + return not( t == "any" or t == "all" or t == "custom") + end + + function StateHandler:ClearAllConditions() + local t = self:GetRule("type") + if t == "custom" then + self:SetRule("custom","") + elseif t == "any" or t == "all" then + self:SetRule("values", {}) + end + ApplyStates(self.bar) + end + + function StateHandler:GetConditionsDisabled() + local t = self:GetRule("type") + return not( t == "any" or t == "all") + end + + function StateHandler:SetCondition(info, key, value) + self:SetRule(ruleMap[key], value or nil, "values") + if value then + self:FixAll(ruleMap[key]) + end + ApplyStates(self.bar) + end + + function StateHandler:GetCondition(info, key) + return self:GetRule("values", ruleMap[key]) or false + end + + function StateHandler:GetCustomDisabled() + return self:GetRule("type") ~= "custom" + end + + function StateHandler:SetCustomRule(info, value) + self:SetRule("custom",value) + ApplyStates(self.bar) + end + + function StateHandler:GetCustomRule() + return self:GetRule("custom") or "" + end + + function StateHandler:ValidateCustomRule(info, value) + local s = value:gsub("%s","") -- remove all spaces + -- unfortunately %b and captures don't support the '+' notation, or this would be considerably simpler + repeat + if s == "" then + return true + end + local c, r = s:match("(%b[])(.*)") + if c == nil and s and #s > 0 then + return format(L["Invalid custom rule '%s': each clause must appear within [brackets]"],value or "") + end + s = r + until c == nil + return true + end + + function StateHandler:GetKeybindDisabled() + return self:GetRule("type") ~= "keybind" + end + + function StateHandler:GetKeybind() + return self:GetRule("keybind") + end + + function StateHandler:SetKeybind(info, value) + if value and #value == 0 then + value = nil + end + self:SetRule("keybind",value) + ApplyStates(self.bar) + end + local function CreateStateOptions(bar, name) local opts = { type = "group", name = name, childGroups = "tab", + args = stateOptions } - local states = tbuild(module.db.profile.bars, bar:GetName(), "states") + opts.handler = StateHandler:New(bar,opts) - local function update() - ApplyStates(bar) - end - - local function setrule( key, value, ... ) - tbuild(states, opts.name, "rule", ...)[key] = value - end - - local function getrule( ... ) - return tfetch(states, opts.name, "rule", ...) - end - - local function setprop(info, value) - SetProperty(bar, opts.name, info[#info], value) - end - - local function getprop(info) - return GetProperty(bar, opts.name, info[#info]) - end - - local function fixall(setkey) - -- if multiple selections in the same group are chosen when 'all' is selected, - -- keep only one of them. If changing the mode, the first in the fields list will - -- be chosen arbitrarily. Otherwise, if selecting a new checkbox from the field-set, - -- it will be retained. - local notified = false - for _, c in ipairs(rules) do - local rule, hidden, fields = unpack(c) - local found = false - for key in ipairs(fields) do - if getrule("values",key) then - if (found or setkey) and key ~= setkey then - setrule(key,false,"values") - if not setkey and not notified then - ReAction:UserError(L["Warning: one or more incompatible rules were turned off"]) - notified = true - end - end - found = true - end - end - end - end - - local function getNeighbors() - local before, after - for k, v in pairs(states) do - local o = tonumber(tfetch(v, "rule", "order")) - if o and k ~= opts.name then - local obefore = tfetch(states,before,"rule","order") - local oafter = tfetch(states,after,"rule","order") - if o < opts.order and (not obefore or obefore < o) then - before = k - end - if o > opts.order and (not oafter or oafter > o) then - after = k - end - end - end - return before, after - end - - local function swapOrder( a, b ) - -- do options table - local args = optionMap[bar].args - args[a].order, args[b].order = args[b].order, args[a].order - -- do profile - a = tbuild(states, a, "rule") - b = tbuild(states, b, "rule") - a.order, b.order = b.order, a.order - end - - local function anchordisable() - return not GetProperty(bar, opts.name, "enableAnchor") - end - - tbuild(states, name) - - opts.order = getrule("order") - if opts.order == nil then - -- add after the highest - opts.order = 100 - for _, state in pairs(states) do - local x = tonumber(tfetch(state, "rule", "order")) - if x and x >= opts.order then - opts.order = x + 1 - end - end - setrule("order",opts.order) - end - - opts.args = { - ordering = { - name = L["Info"], - order = 1, - type = "group", - args = { - delete = { - name = L["Delete this State"], - order = -1, - type = "execute", - func = function(info) - if states[opts.name] then - states[opts.name] = nil - ApplyStates(bar) - end - optionMap[bar].args[opts.name] = nil - end, - }, - rename = { - name = L["Name"], - order = 1, - type = "input", - get = function() return opts.name end, - set = function(info, value) - -- check for existing state name - if states[value] then - format(L["State named '%s' already exists"],value) - end - local args = optionMap[bar].args - states[value], args[value], states[opts.name], args[opts.name] = states[opts.name], args[opts.name], nil, nil - opts.name = value - update() - end, - pattern = "^%w*$", - usage = L["State names must be alphanumeric without spaces"], - }, - ordering = { - name = L["Evaluation Order"], - desc = L["State transitions are evaluated in the order listed:\nMove a state up or down to change the order"], - order = 2, - type = "group", - inline = true, - args = { - up = { - name = L["Up"], - order = 1, - type = "execute", - width = "half", - func = function() - local before, after = getNeighbors() - if before then - swapOrder(before, opts.name) - update() - end - end, - }, - down = { - name = L["Down"], - order = 2, - type = "execute", - width = "half", - func = function() - local before, after = getNeighbors() - if after then - swapOrder(opts.name, after) - update() - end - end, - } - } - } - } - }, - properties = { - name = L["Properties"], - order = 2, - type = "group", - args = { - desc = { - name = L["Set the properties for the bar when in this state"], - order = 1, - type = "description" - }, - hide = { - name = L["Hide Bar"], - order = 2, - type = "toggle", - set = setprop, - get = getprop, - }, - page = { - name = L["Show Page #"], - order = 3, - type = "select", - disabled = function() - --return bar:GetNumPages() < 2 - return true - end, - hidden = function() - --return bar:GetNumPages() < 2 - return true - end, - values = function() - -- use off-by-one ordering to put (none) first in the list - local pages = { [1] = L["(none)"] } - --for i = 1, bar:GetNumPages() do - -- pages[i+1] = i - --end - return pages - end, - set = function(info, value) - value = value - 1 - setprop(info, value > 0 and value or nil) - end, - get = function(info) - return getprop(info) or L["(none)"] - end, - }, - keybindstate = { - name = L["Override Keybinds"], - desc = L["Set this state to maintain its own set of keybinds which override the defaults when active"], - order = 4, - type = "toggle", - set = setprop, - get = getprop, - }, - position = { - name = L["Position"], - order = 5, - type = "group", - inline = true, - args = { - enableAnchor = { - name = L["Set New Position"], - order = 1, - type = "toggle", - set = setprop, - get = getprop, - }, - anchorPoint = { - name = L["Point"], - order = 2, - type = "select", - values = pointTable, - set = function(info, value) setprop(info, value ~= "NONE" and value or nil) end, - get = function(info) return getprop(info) or "NONE" end, - disabled = anchordisable, - hidden = anchordisable, - }, - anchorRelPoint = { - name = L["Relative Point"], - order = 3, - type = "select", - values = pointTable, - set = function(info, value) setprop(info, value ~= "NONE" and value or nil) end, - get = function(info) return getprop(info) or "NONE" end, - disabled = anchordisable, - hidden = anchordisable, - }, - anchorX = { - name = L["X Offset"], - order = 4, - type = "range", - min = -100, - max = 100, - step = 1, - set = setprop, - get = getprop, - disabled = anchordisable, - hidden = anchordisable, - }, - anchorY = { - name = L["Y Offset"], - order = 5, - type = "range", - min = -100, - max = 100, - step = 1, - set = setprop, - get = getprop, - disabled = anchordisable, - hidden = anchordisable, - }, - }, - }, - scale = { - name = L["Scale"], - order = 6, - type = "group", - inline = true, - args = { - enableScale = { - name = L["Set New Scale"], - order = 1, - type = "toggle", - set = setprop, - get = getprop, - }, - scale = { - name = L["Scale"], - order = 2, - type = "range", - min = 0.1, - max = 2.5, - step = 0.05, - isPercent = true, - set = setprop, - get = function(info) return getprop(info) or 1 end, - disabled = function() return not GetProperty(bar, opts.name, "enableScale") end, - hidden = function() return not GetProperty(bar, opts.name, "enableScale") end, - }, - }, - }, - }, - }, - rules = { - name = L["Rule"], - order = 3, - type = "group", - args = { - mode = { - name = L["Select this state"], - order = 2, - type = "select", - style = "radio", - values = { - default = L["by default"], - any = L["when ANY of these"], - all = L["when ALL of these"], - custom = L["via custom rule"], - keybind = L["via keybinding"], - }, - set = function( info, value ) - setrule("type", value) - fixall() - update() - end, - get = function( info ) - return getrule("type") - end, - }, - clear = { - name = L["Clear All"], - order = 3, - type = "execute", - hidden = function() - local t = getrule("type") - return t ~= "any" and t ~= "all" - end, - disabled = function() - local t = getrule("type") - return t ~= "any" and t ~= "all" - end, - func = function() - local type = getrule("type") - if type == "custom" then - setrule("custom","") - elseif type == "any" or type == "all" then - setrule("values", {}) - end - update() - end, - }, - inputs = { - name = L["Conditions"], - order = 4, - type = "multiselect", - hidden = function() - local t = getrule("type") - return t ~= "any" and t ~= "all" - end, - disabled = function() - local t = getrule("type") - return t ~= "any" and t ~= "all" - end, - values = ruleSelect, - set = function(info, key, value ) - setrule(ruleMap[key], value or nil, "values") - if value then - fixall(ruleMap[key]) - end - update() - end, - get = function(info, key) - return getrule("values", ruleMap[key]) or false - end, - }, - custom = { - name = L["Custom Rule"], - order = 5, - type = "input", - multiline = true, - hidden = function() - return getrule("type") ~= "custom" - end, - disabled = function() - return getrule("type") ~= "custom" - end, - desc = L["Syntax like macro rules: see preset rules for examples"], - set = function(info, value) - setrule("custom",value) - update() - end, - get = function(info) - return getrule("custom") or "" - end, - validate = function (info, rule) - local s = rule:gsub("%s","") -- remove all spaces - -- unfortunately %b and captures don't support the '+' notation, or this would be considerably simpler - repeat - if s == "" then - return true - end - local c, r = s:match("(%b[])(.*)") - if c == nil and s and #s > 0 then - return format(L["Invalid custom rule '%s': each clause must appear within [brackets]"],rule) - end - s = r - until c == nil - return true - end, - }, - keybind = { - name = L["Keybinding"], - order = 6, - inline = true, - hidden = function() return getrule("type") ~= "keybind" end, - disabled = function() return getrule("type") ~= "keybind" end, - type = "group", - args = { - desc = { - name = L["Invoking a state keybind toggles an override of all other transition rules."], - order = 1, - type = "description", - }, - keybind = { - name = L["State Hotkey"], - desc = L["Define an override toggle keybind"], - order = 2, - type = "keybinding", - set = function(info, value) - if value and #value == 0 then - value = nil - end - setrule("keybind",value) - update() - end, - get = function() return getrule("keybind") end, - }, - }, - }, - }, - }, - } return opts end - CreateBarOptions = function(bar) + function RegisterPropertyOptions( field, options, handler ) + stateOptions.properties.plugins[field] = options + if handler then + for k,v in pairs(handler) do + StateHandler[k] = v + end + end + end + + + function module:GetBarOptions(bar) local private = { } local states = tbuild(module.db.profile.bars, bar:GetName(), "states") local options = { @@ -954,17 +1021,33 @@ } } } - local states = tfetch(module.db.profile.bars, bar:GetName(), "states") - if states then - for name, config in pairs(states) do - options.args[name] = CreateStateOptions(bar,name) - end + for name, config in pairs(states) do + options.args[name] = CreateStateOptions(bar,name) end optionMap[bar] = options return options end end -function module:GetBarOptions(bar) - return CreateBarOptions(bar) +-- Module API -- + +-- Pass in a property field-name, an implementation function, a static options table, and an +-- optional options handler method-table +-- +-- propertyImplFunc prototype: +-- propertyImplFunc( bar, stateTable ) +-- where stateTable is a { ["statename"] = { state config } } table. +-- +-- The options table is static, i.e. not bar-specific and should only reference handler method +-- strings (either existing ones or those added via optHandler). The existing options are ordered +-- 91-100. Order #1 is reserved for the heading. +-- +-- The contents of optHandler, if provided, will be added to the existing StateHandler metatable. +-- See above, for existing API. In particular see the properties set up in the New method: self.bar, +-- self.states, and self:GetName(), and the generic property handlers self:GetProp() and self:SetProp(). +-- +function module:RegisterStateProperty( field, propertyImplFunc, options, optHandler ) + RegisterProperty(field, propertyImplFunc) + RegisterPropertyOptions(field, options, optHandler) end +