Mercurial > wow > reaction
diff Bar.lua @ 77:da8ba8783924
- added revision updater to each code file
- Changed button/bar class mechanic to metatable-based
- Changed buttons to live within a sub-frame, to play nicely between show-empty-buttons and hidestates
- bar frame is now available only via accessor
- Changed some semantics with AddButton/PlaceButton
- Cleaned up action buttons options, fixed hide-when-empty option
- moved show-action-ID-label as a button method
- converted drag overlay from nested-frame to :Raise()
- fixed ReAction:SetConfigMode() to not call event when mode doesn't change
- Fixed ordering for dynamic state tab (always last)
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Mon, 23 Jun 2008 22:27:50 +0000 |
parents | 06cd74bdc7da |
children | 57f8151ea0f0 |
line wrap: on
line diff
--- a/Bar.lua Thu Jun 19 17:48:57 2008 +0000 +++ b/Bar.lua Mon Jun 23 22:27:50 2008 +0000 @@ -7,18 +7,16 @@ local format = string.format local SecureStateHeader_Refresh = SecureStateHeader_Refresh - --- update ReAction revision if this file is newer -local revision = tonumber(("$Revision$"):match("%d+")) -if revision > ReAction.revision then - ReAction.revision = revision -end +ReAction:UpdateRevision("$Revision$") ------ BAR CLASS ------ local Bar = { _classID = {} } +ReAction.Bar = Bar -- export to ReAction -local function Constructor( self, name, config ) +function Bar:New( name, config ) + -- create new self + self = setmetatable( { }, {__index = Bar} ) if type(config) ~= "table" then error("ReAction.Bar: config table required") end @@ -32,24 +30,43 @@ local parent = config.parent and (ReAction:GetBar(config.parent) or _G[config.parent]) or UIParent local f = CreateFrame("Button",name and format("ReAction-%s",name),parent,"SecureStateHeaderTemplate, SecureActionButtonTemplate") - - -- The frame itself is read-only - function self:GetFrame() - return f - end + f:SetFrameStrata("MEDIUM") + f:SetWidth(config.width) + f:SetWidth(config.height) + f:Show() -- The bar itself is also a Button derived from SecureActionButtonTemplate, so it has an OnClick handler -- which we can use as a virtual button for keybinds, which will send attribute-value changes to itself. -- However, we don't ever want the user to be able to click it directly. f:EnableMouse(false) f:SetAttribute("type","attribute") - f:SetFrameStrata("MEDIUM") - f:SetWidth(config.width) - f:SetWidth(config.height) - f:Show() + + -- Buttons are contained in an anonymous intermediate sub-frame. This arrangement is to specifically + -- address the issue of the interaction with hidestates and auto-hiding empty action buttons (the two + -- don't play nicely together). It also has the fringe benefit of making show/hide faster because a + -- single frame is shown/hidden instead of potentially dozens. Unfortunately it does add an extra layer + -- of indirection to all state changes, as a secondary (trivial) statemap must be invoked. This + -- complicates frame setup slightly. + local bf = CreateFrame("Frame", nil, f, "SecureStateHeaderTemplate") + bf:SetAllPoints() + bf:Show() + bf:SetAttribute("useparent*",true) -- this facilitates SecureButton_GetModifiedAttribute() + bf:SetAttribute("statemap-parent","*:=") -- however some methods don't use it, so propagate the state too + f:SetAttribute("addchild",bf) + + -- Both frames are read-only. Override the default accessors for this object. + function self:GetFrame() + return f + end + + function self:GetButtonFrame() + return bf + end self:ApplyAnchor() ReAction.RegisterCallback(self, "OnConfigModeChanged") + + return self end function Bar:Destroy() @@ -158,6 +175,18 @@ return self.name end +function Bar:GetFrame() + -- this method is included for documentation purposes. It is overridden + -- in the New method for each object. + error("Invalid Bar object: used without initialization") +end + +function Bar:GetButtonFrame() + -- this method is included for documentation purposes. It is overridden + -- in the New method for each object. + error("Invalid Bar object: used without initialization") +end + -- only ReAction:RenameBar() should call this function function Bar:SetName(name) self.name = name @@ -168,7 +197,9 @@ end function Bar:AddButton(idx, button) + -- store in a reverse-index array self.buttons[button] = idx + self:GetButtonFrame():SetAttribute("addchild",button:GetFrame()) SecureStateHeader_Refresh(self:GetFrame()) end @@ -234,7 +265,7 @@ end end --- Set an attribute on the frame (or its buttons if 'doButtons' = true) +-- Set an attribute on the frame (or buttonFrame if 'buttonFrame' = true) -- Either or both 'map' and 'default' can be passed: -- - If 'map' is omitted, then 'default' is set to the attribute. -- - If 'map' is provided, then it is interpreted as an unordered @@ -243,7 +274,8 @@ -- string, e.g. "<state1>:<value1>;<state2>:<value2>". If 'default' -- is also provided, then its value will be converted to a string -- and appended. -function Bar:SetStateAttribute( attribute, map, default, doButtons ) +function Bar:SetStateAttribute( attribute, map, default, buttonFrame ) + local f = buttonFrame and self:GetButtonFrame() or self:GetFrame() local value = default if map then local tmp = { } @@ -255,29 +287,6 @@ end value = table.concat(tmp,";") end - if doButtons then - for b in pairs(self.buttons) do - local f = b.GetFrame and b:GetFrame() - if f then - f:SetAttribute(attribute, value) - end - end - else - self:GetFrame():SetAttribute(attribute, value) - end - SecureStateHeader_Refresh(self:GetFrame()) + f:SetAttribute(attribute, value) + SecureStateHeader_Refresh(f) end - - ------- Export as a class-factory ------ -ReAction.Bar = { - prototype = Bar, - New = function(self, ...) - local x = { } - for k,v in pairs(Bar) do - x[k] = v - end - Constructor(x, ...) - return x - end -}