diff Button.lua @ 1:c11ca1d8ed91

Version 0.1
author Flick <flickerstreak@gmail.com>
date Tue, 20 Mar 2007 21:03:57 +0000
parents
children 8e0ff8ae4c08
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Button.lua	Tue Mar 20 21:03:57 2007 +0000
@@ -0,0 +1,806 @@
+-- private constants
+local namePrefix = "ReActionButton_"
+local _G = getfenv(0)
+local ACTION_FREE = { }
+local MAX_ACTIONS = 120
+
+local hotKeyDefaultColor    = { r=1.0, g=1.0, b=1.0, a=1.0 }
+local hotKeyDisabledColor   = { r=0.6, g=0.6, b=0.6, a=1.0 }
+local hotKeyOutOfRangeColor = { r=1.0, g=0.2, b=0.2, a=1.0 }
+
+local hotKeyModifierColors = {
+  S = { r=0.6, g=0.6, b=1.0, a=1.0 },  -- shift
+  C = { r=1.0, g=0.82, b=0, a=1.0 },  -- ctrl
+  A = { r=0.1, g=1.0, b=0.1, a=1.0 },  -- alt
+}
+
+local equippedActionBorderColor = { r=0, g=1.0, b=0, a=0.35 }
+
+local actionUsableColor        = { r=1.0, g=1.0, b=1.0, a=1.0 }
+local actionNotUsableColor     = { r=0.4, g=0.4, b=0.4, a=1.0 }
+local actionNotEnoughManaColor = { r=0.2, g=0.2, b=0.7, a=1.0 }
+local actionOutOfRangeColor    = { r=1.0, g=0.2, b=0.2, a=1.0 }
+
+-- private variables
+local kbValidate = AceLibrary("AceConsole-2.0").keybindingValidateFunc
+local actionButtonTbl = { }
+
+
+
+-- ReActionButton is a class prototype object.
+ReActionButton = AceLibrary("AceOO-2.0").Class("AceEvent-2.0")
+
+-------------------
+-- Class methods
+-------------------
+
+-- In addition to supporting the 'new' creation method (in which case an action ID must be specified directly),
+-- ReActionButton supports the 'acquire'/'release' creation method, which recycles objects and manages actionID assignment.
+
+function ReActionButton:acquire(parent, config, barIdx)
+  local id = nil
+  for i = 1, MAX_ACTIONS do
+    if actionButtonTbl[i] == nil or actionButtonTbl[i].inUse == false then
+      id = i
+      break
+    end
+  end
+
+  if id == nil then return nil end  -- all buttons and action ids are in use
+
+  local hint = config.actionIDs[barIdx]
+  if hint and (actionButtonTbl[hint] == nil or actionButtonTbl[hint].inUse == false) then
+    id = hint
+  end
+
+  if actionButtonTbl[id] == nil then 
+    actionButtonTbl[id] = { }
+  end
+  local t = actionButtonTbl[id]
+
+  t.inUse = true
+  if t.button then
+    t.button:Configure(parent,config,barIdx,id)
+  else
+    t.button = self:new(parent,config,barIdx,id)
+  end
+
+  if actionButtonTbl[t.button:GetActionID()].inUse ~= true then
+  end
+
+  return t.button
+end
+
+function ReActionButton:release( b )
+  if b then
+    actionButtonTbl[b:GetActionID()].inUse = false
+    b:Recycle()
+  end
+end
+
+
+
+function ReActionButton:ShowAllActionIDs()
+  for _, b in ipairs(actionButtonTbl) do
+    b:ShowActionID()
+  end
+end
+
+function ReActionButton:HideAllActionIDs()
+  for _, b in ipairs(actionButtonTbl) do
+    b:HideActionID()
+  end
+end
+
+
+----------------------
+-- Instance methods
+----------------------
+function ReActionButton.prototype:init( parentFrame, config, barIdx, id )
+  ReActionButton.super.prototype.init(self)
+
+  -- create the button widget
+  self.name = namePrefix.."_"..id
+  self.button = CreateFrame("CheckButton", self.name, parentFrame, "ReActionButtonTemplate")
+  
+  -- create the actionID label on the control widget
+  local actionIDLabel = self.button:CreateFontString(nil,"ARTWORK", "NumberFontNormalSmall")
+  actionIDLabel:SetPoint("BOTTOMLEFT",0,0)
+  actionIDLabel:Hide()
+
+  -- store references to the various sub-frames so we don't have to look it up all the time
+  self.frames      = {
+    hotkey         = _G[self.name.."HotKey"],
+    count          = _G[self.name.."Count"],
+    cooldown       = _G[self.name.."Cooldown"],
+--    nCooldown      = _G[self.name.."CooldownNumeric"],
+    macro          = _G[self.name.."Name"],
+    icon           = _G[self.name.."Icon"],
+    border         = _G[self.name.."Border"],
+    normalTexture  = _G[self.name.."NormalTexture"],
+    flash          = _G[self.name.."Flash"],
+    actionID       = actionIDLabel
+  }
+
+  -- provide a reference back to this object for the frame to use in event handlers
+  self.button.rxnBtn = self
+
+  -- initialize
+  self:Configure(parentFrame, config, barIdx, id)
+end
+
+function ReActionButton.prototype:Recycle()
+  local b = self.button
+  local action = self:GetActionID()
+
+  self.config.actionIDs[self.barIdx] = nil
+
+  self:SetKeyBinding(nil)
+  self:UpdateDisplay()
+  b:UnregisterAllEvents()
+  b:Hide()
+  b:ClearAllPoints()
+  b:SetParent(ReActionButtonRecycleFrame)
+end
+
+
+
+-- set the button location
+function ReActionButton.prototype:PlaceButton(point, x, y, sz)
+  local b = self.button
+  local scale = sz / 36
+  b:ClearAllPoints()
+  b:SetScale( scale )
+  b:SetPoint(point,x/scale,y/scale)
+end
+
+
+function ReActionButton.prototype:ShowActionID()
+  self.frames.actionID:Show()
+end
+
+function ReActionButton.prototype:HideActionID()
+  self.frames.actionID:Hide()
+end
+
+
+
+-- configuration and setup
+function ReActionButton.prototype:Configure( parentFrame, config, barIdx, id )
+  self.config   = config
+  self.barIdx   = barIdx
+  self.showGrid = config.showGrid and 1 or 0
+
+  self.button:ClearAllPoints()
+  self.button:SetParent(parentFrame)
+
+  self:SetupAttributes()
+  self:RegisterStaticEvents()
+
+  if id then
+    -- set action ID
+    self:SetActionID(id)
+  else
+    self:ApplyActionID()
+  end
+  self:ApplyLayout()
+  self:ApplyStyle()
+
+  self:UpdateDisplay()
+end
+
+function ReActionButton.prototype:SetupAttributes()
+  local b = self.button
+  b:SetAttribute("type", "action")
+	b:SetAttribute("shift-type*", ATTRIBUTE_NOOP)
+  b:SetAttribute("alt-type*", ATTRIBUTE_NOOP)
+	b:SetAttribute("checkselfcast", true)
+	b:SetAttribute("useparent-unit", true)
+end
+
+function ReActionButton.prototype:RegisterStaticEvents()
+	self:RegisterEvent("PLAYER_ENTERING_WORLD")
+	self:RegisterEvent("ACTIONBAR_SLOT_CHANGED")
+	self:RegisterEvent("UPDATE_BINDINGS")
+  self:RegisterEvent("ACTIONBAR_SHOWGRID")
+  self:RegisterEvent("ACTIONBAR_HIDEGRID")
+end
+
+function ReActionButton.prototype:RegisterActionEvents()
+  self:RegisterEvent("ACTIONBAR_UPDATE_STATE")
+  self:RegisterEvent("ACTIONBAR_UPDATE_USABLE")
+  self:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN", "ACTIONBAR_UPDATE_USABLE")
+  self:RegisterEvent("UPDATE_INVENTORY_ALERTS", "ACTIONBAR_UPDATE_USABLE")
+  self:RegisterEvent("PLAYER_AURAS_CHANGED", "ACTIONBAR_UPDATE_USABLE")
+  self:RegisterEvent("PLAYER_TARGET_CHANGED", "ACTIONBAR_UPDATE_USABLE")
+  self:RegisterEvent("UNIT_INVENTORY_CHANGED")
+  self:RegisterEvent("CRAFT_SHOW")
+  self:RegisterEvent("CRAFT_CLOSE", "CRAFT_SHOW")
+  self:RegisterEvent("TRADE_SKILL_SHOW", "CRAFT_SHOW")
+  self:RegisterEvent("TRADE_SKILL_CLOSE", "CRAFT_SHOW")
+  self:RegisterEvent("PLAYER_ENTER_COMBAT", "CRAFT_SHOW")
+  self:RegisterEvent("PLAYER_LEAVE_COMBAT")
+  self:RegisterEvent("START_AUTOREPEAT_SPELL")
+  self:RegisterEvent("STOP_AUTOREPEAT_SPELL")
+
+  self.button:SetScript("OnUpdate", function() self:OnUpdate(arg1) end)
+  self.actionEventsRegistered = true
+end
+
+function ReActionButton.prototype:UnregisterActionEvents()
+  self:UnregisterEvent("ACTIONBAR_UPDATE_STATE")
+  self:UnregisterEvent("ACTIONBAR_UPDATE_USABLE")
+  self:UnregisterEvent("ACTIONBAR_UPDATE_COOLDOWN")
+  self:UnregisterEvent("UPDATE_INVENTORY_ALERTS")
+  self:UnregisterEvent("PLAYER_AURAS_CHANGED")
+  self:UnregisterEvent("PLAYER_TARGET_CHANGED")
+  self:UnregisterEvent("UNIT_INVENTORY_CHANGED")
+  self:UnregisterEvent("CRAFT_SHOW")
+  self:UnregisterEvent("CRAFT_CLOSE")
+  self:UnregisterEvent("TRADE_SKILL_SHOW")
+  self:UnregisterEvent("TRADE_SKILL_CLOSE")
+  self:UnregisterEvent("PLAYER_ENTER_COMBAT")
+  self:UnregisterEvent("PLAYER_LEAVE_COMBAT")
+  self:UnregisterEvent("START_AUTOREPEAT_SPELL")
+  self:UnregisterEvent("STOP_AUTOREPEAT_SPELL")
+
+  self.button:SetScript("OnUpdate", nil)
+  self.actionEventsRegistered = false
+end
+
+
+-- event handlers
+function ReActionButton.prototype:ACTIONBAR_SLOT_CHANGED()
+  if arg1 == 0 or arg1 == self:GetActionID() then
+    self:UpdateDisplay()
+  end
+end
+
+function ReActionButton.prototype:PLAYER_ENTERING_WORLD()
+  self:UpdateDisplay()
+end
+
+function ReActionButton.prototype:UPDATE_BINDINGS()
+  self:UpdateDisplay()
+end
+
+function ReActionButton.prototype:ACTIONBAR_SHOWGRID()
+  self:ShowGridTmp()
+end
+
+function ReActionButton.prototype:ACTIONBAR_HIDEGRID()
+  self:HideGridTmp()
+end
+
+function ReActionButton.prototype:ACTIONBAR_UPDATE_STATE()
+  self:UpdateCheckedState()
+end
+
+function ReActionButton.prototype:ACTIONBAR_UPDATE_USABLE()
+  self:UpdateUsable()
+  self:UpdateCooldown()
+  self:ColorHotKey()
+end
+
+function ReActionButton.prototype:UNIT_INVENTORY_CHANGED()
+  if arg1 == "player" then
+    self:UpdateDisplay()
+  end
+end
+
+function ReActionButton.prototype:CRAFT_SHOW()
+  self:UpdateCheckedState()
+end
+
+function ReActionButton.prototype:PLAYER_ENTER_COMBAT()
+  if IsAttackAction(self:GetActionID()) then
+    self:StartFlash()
+  end
+end
+
+function ReActionButton.prototype:PLAYER_LEAVE_COMBAT()
+  if IsAttackAction(self:GetActionID()) then
+    self:StopFlash()
+  end
+end
+
+function ReActionButton.prototype:START_AUTOREPEAT_SPELL()
+  if IsAutoRepeatAction(self:GetActionID()) then
+    self:StartFlash()
+  end
+end
+
+function ReActionButton.prototype:STOP_AUTOREPEAT_SPELL()
+  if self:IsFlashing() and not IsAttackAction(self:GetActionID()) then
+    self:StopFlash()
+  end
+end
+
+
+-- OnUpdate handler
+function ReActionButton.prototype:OnUpdate(elapsed)
+  local action = self:GetActionID()
+  local f = self.frames
+
+  -- handle flashing
+	if self:IsFlashing() then
+		self.flashtime = self.flashtime - elapsed
+		if self.flashtime <= 0 then
+			local overtime = -self.flashtime
+			if overtime >= ATTACK_BUTTON_FLASH_TIME then
+				overtime = 0
+			end
+			self.flashtime = ATTACK_BUTTON_FLASH_TIME - overtime
+
+			if f.flash:IsVisible() then
+        f.flash:Hide()
+      else
+        f.flash:Show()
+			end
+		end
+	end
+	
+	-- Handle range indicator
+	if self.rangeTimer then
+		self.rangeTimer = self.rangeTimer - elapsed
+		if self.rangeTimer <= 0 then
+      self:ColorHotKey()
+      self:UpdateUsable()
+			self.rangeTimer = TOOLTIP_UPDATE_TIME
+		end
+	end
+
+  -- handle toltip update
+  if self.tooltipTime then
+    self.tooltipTime = self.tooltipTime - elapsed
+    if self.tooltipTime <= 0 then
+      if GameTooltip:IsOwned(self.button) then
+        self:UpdateTooltip()
+      else
+        self.tooltipTime = nil
+      end
+    end
+  end
+end
+
+
+
+
+-- keybinding functions
+function ReActionButton.prototype:SetKeyBinding( k )
+  if k == nil or kbValidate(k) then
+    local current = self:GetKeyBinding()
+  	ClearOverrideBindings(self.button)
+    if current then
+      SetBinding(current,nil)
+    end
+    if k then
+      SetBindingClick(k, self.name, "LeftButton")
+    end
+  end
+end
+
+function ReActionButton.prototype:GetKeyBinding()
+  return GetBindingKey("CLICK "..self.name..":LeftButton")
+end
+
+function ReActionButton.prototype:ShowAssignKeybinding()
+  local f = ReActionKeybindFrame
+  f:ClearAllPoints()
+  f:SetPoint("BOTTOM", self.button, "TOP", 0, 10)
+  ReActionKeybindFrameButton.keybindTarget = self
+  local k = self:GetKeyBinding()
+  if k then
+    local txt = GetBindingText(k, "KEY_")
+    ReActionKeybindFrameButton:SetText(txt or "")
+  end
+  f:Show()
+end
+
+
+local mouseButtonConvert = {
+  LeftButton = "BUTTON1",
+  RightButton = "BUTTON2",
+  MiddleButton = "BUTTON3",
+  Button4 = "BUTTON4",
+  Button5 = "BUTTON5"
+}
+
+function ReActionButton.prototype:HandleKeybindAssign(button, key, mouseButton)
+  mouseButton = mouseButton and mouseButtonConvert[mouseButton]
+  if mouseButton ~= "BUTTON1" and mouseButton ~= "BUTTON2" then
+    key = key or mouseButton
+    if key == nil or key == "UNKNOWN" or key == "SHIFT" or key == "CTRL" or key == "ALT" then 
+      return
+    end
+    if key == "ESCAPE" then
+      ReActionKeybindFrame:Hide()
+      return
+    end
+		if IsShiftKeyDown() then 
+      key = "SHIFT-"..key
+    end
+		if IsControlKeyDown() then
+			key = "CTRL-"..key
+		end
+		if IsAltKeyDown() then
+			keyPressed = "ALT-"..key
+		end
+    local oldAction = GetBindingAction(key)
+    local oldKey = self:GetKeyBinding()
+    if oldAction then
+      -- can't pop a modal dialog box, will need to think something up
+    end
+    if oldKey == key then
+      SetBinding(key,nil)
+      key = nil
+    end
+    self:SetKeyBinding(key)
+    button:SetText(key and GetBindingText(key, "KEY_") or "")
+    self:UpdateDisplay()
+    SaveBindings(2) -- 2 = character specific bindings... hmm...
+  end
+  button.selected = false
+  this:SetButtonState("NORMAL")
+end
+
+
+-- action ID functions
+function ReActionButton.prototype:SetActionID( id )
+  self.config.actionIDs[self.barIdx] = tonumber(id) -- force data integrity
+  self:ApplyActionID()
+end
+
+function ReActionButton.prototype:GetActionID()
+  return self.config.actionIDs[self.barIdx]
+end
+
+function ReActionButton.prototype:ApplyActionID()
+  local action = tonumber(self:GetActionID())
+  self.button:SetAttribute("action",action or nil)
+  self.frames.actionID:SetText(action or "")
+end
+
+function ReActionButton.prototype:ShowActionID()
+  self.frames.actionID:Show()
+end
+
+function ReActionButton.prototype:HideActionID()
+  self.frames.actionID:Hide()
+end
+
+function ReActionButton:ShowAllActionIDs() -- class-wide function
+  for _, tbl in pairs(actionButtonTbl) do
+    if tbl.button then tbl.button:ShowActionID() end
+  end
+end
+
+function ReActionButton:HideAllActionIDs() -- class-wide function
+  for _, tbl in pairs(actionButtonTbl) do
+    if tbl.button then tbl.button:HideActionID() end
+  end
+end
+
+
+-- action transfer functions
+function ReActionButton.prototype:ShouldPickupAction(mouseButton)
+	return IsShiftKeyDown() and not SecureButton_GetModifiedAttribute(self.button, "type", mouseButton)
+end
+
+function ReActionButton.prototype:ShowGridTmp()
+  self.showGrid = self.showGrid + 1
+  self:UpdateVisibility()
+end
+
+function ReActionButton.prototype:HideGridTmp()
+  self.showGrid = self.showGrid - 1
+  self:UpdateVisibility()
+end
+
+function ReActionButton.prototype:ShowGrid()
+  self.config.showGrid = true
+  self:ShowGridTmp()
+end
+
+function ReActionButton.prototype:HideGrid()
+  self.config.showGrid = false
+  self:HideGridTmp()
+end
+
+
+
+-- layout & style functions
+function ReActionButton.prototype:ApplyLayout()
+  local f = self.frames
+
+  if self.config.keyBindLoc then
+    local h = f.hotkey
+    local loc = self.config.keyBindLoc
+    h:ClearAllPoints()
+    h:SetPoint(loc,0,0)
+    local j
+    if string.match(loc,"LEFT") then
+      j = "LEFT"
+    elseif string.match(loc,"RIGHT") then
+      j = "RIGHT"
+    else
+      j = "CENTER"
+    end
+    h:SetJustifyH(j)
+  end
+
+  if self.config.stackCountLoc then
+    local c = f.count
+    local loc = self.config.stackCountLoc
+    c:ClearAllPoints()
+    c:SetPoint(loc,0,0)
+    local j
+    if string.match(loc,"LEFT") then
+      j = "LEFT"
+    elseif string.match(loc,"RIGHT") then
+      j = "RIGHT"
+    else
+      j = "CENTER"
+    end
+    c:SetJustifyH(j)
+  end
+
+  if self.config.showKeyBind then
+    f.hotkey:Show()
+  else
+    f.hotkey:Hide()
+  end
+    
+  if self.config.showStackCount then
+    f.count:Show()
+  else
+    f.count:Hide()
+  end
+
+--[[
+  if self.config.showNumericCooldown then
+    f.nCooldown:Show()
+  else
+    f.nCooldown:Hide()
+  end
+]]
+
+  if self.config.showMacroName then
+    f.macro:Show()
+  else
+    f.macro:Hide()
+  end
+end
+
+function ReActionButton.prototype:ApplyStyle()
+  local f = self.frames
+  -- for now, just a static style
+  f.hotkey:SetFontObject(NumberFontNormal)
+  f.count:SetFontObject(NumberFontNormalYellow)
+end
+
+
+
+-- start/stop flashing
+function ReActionButton.prototype:StartFlash()
+  self.flashing = true
+  self.flashtime = 0
+  self:UpdateCheckedState()
+end
+
+function ReActionButton.prototype:StopFlash()
+  self.flashing = false
+  self.frames.flash:Hide()
+  self:UpdateCheckedState()
+end
+
+function ReActionButton.prototype:IsFlashing()
+  return self.flashing
+end
+
+
+
+
+
+-- set the tooltip
+function ReActionButton.prototype:SetTooltip()
+  GameTooltip_SetDefaultAnchor(GameTooltip, self.button)
+  self:UpdateTooltip()
+end
+
+function ReActionButton.prototype:ClearTooltip()
+  tooltipTime = nil
+  GameTooltip:Hide()
+end
+
+
+
+-- colorize the hotkey
+function ReActionButton.prototype:ColorHotKey()
+  local action = self:GetActionID()
+  local c = hotKeyDefaultColor
+
+  if action and HasAction(action) then
+    if IsActionInRange(action) == 0 then
+      c = hotKeyOutOfRangeColor
+    elseif self.config.keyBindColorCode then
+      local modKey = string.match( self.frames.hotkey:GetText() or "", "([ACS])%-")
+      c = modKey and hotKeyModifierColors[modKey] or c
+    end
+  else
+    c = hotKeyDisabledColor
+  end
+
+  self.frames.hotkey:SetTextColor(c.r, c.g, c.b)
+end
+
+
+
+
+-- display update functions
+function ReActionButton.prototype:UpdateDisplay()
+  self:UpdateIcon()
+  self:UpdateHotkey()
+  self:UpdateCount()
+  self:UpdateMacroText()
+  self:UpdateUsable()
+  self:UpdateCooldown()
+  self:UpdateFlash()
+  self:UpdateEvents()
+  self:UpdateVisibility()
+  self:UpdateTooltip()
+end
+
+function ReActionButton.prototype:UpdateIcon()
+  local f = self.frames
+  local b = self.button
+
+  local action = self:GetActionID()
+  local texture = action and GetActionTexture(action)
+
+  if action and texture then
+    f.icon:SetTexture(texture)
+    f.icon:Show()
+    self.rangeTimer = -1
+    b:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
+  else
+    f.icon:Hide()
+    f.cooldown:Hide()
+    self.rangeTimer = nil
+    b:SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
+  end
+
+  self:UpdateCheckedState()
+
+  -- Add a green border if action is an equipped item
+  if action and IsEquippedAction(action) then
+    local c = equippedActionBorderColor
+    f.border:SetVertexColor(c.r, c.g, c.b, c.a or 1)
+    f.border:Show()
+  else
+    f.border:Hide()
+  end
+end
+
+function ReActionButton.prototype:UpdateCheckedState()
+  local action = self:GetActionID()
+	if action and (IsCurrentAction(action) or IsAutoRepeatAction(action)) then
+		self.button:SetChecked(1)
+	else
+		self.button:SetChecked(0)
+	end
+end
+
+
+function ReActionButton.prototype:UpdateHotkey()
+  local action = self:GetActionID()
+  local b = self.button
+  local f = self.frames
+  local key = self:GetKeyBinding()
+  local txt = GetBindingText(key, "KEY_",1)
+
+  if txt then
+    f.hotkey:SetText(string.upper(txt))
+    self:ColorHotKey()
+  else
+    f.hotkey:SetText("")
+  end
+end
+
+function ReActionButton.prototype:UpdateCount()
+  local action = self:GetActionID()
+	if action and (IsConsumableAction(action) or IsStackableAction(action)) then
+		self.frames.count:SetText(GetActionCount(action))
+	else
+		self.frames.count:SetText("")
+	end
+end
+
+function ReActionButton.prototype:UpdateMacroText()
+  local action = self:GetActionID()
+	self.frames.macro:SetText(action and GetActionText(action) or "")
+end
+
+function ReActionButton.prototype:UpdateUsable()
+  local f = self.frames
+  local action = self:GetActionID()
+	local isUsable, notEnoughMana
+  if action then
+    isUsable, notEnoughMana = IsUsableAction(action)
+  end
+	if isUsable then
+    local c = actionUsableColor
+    if IsActionInRange(action) == 0 then
+      c = actionOutOfRangeColor
+    else
+  		f.normalTexture:SetVertexColor(c.r, c.g, c.b, c.a)
+    end
+		f.icon:SetVertexColor(c.r, c.g, c.b, c.a)
+	elseif notEnoughMana then
+    local c = actionNotEnoughManaColor
+		f.icon:SetVertexColor(c.r, c.g, c.b, c.a)
+		f.normalTexture:SetVertexColor(c.r, c.g, c.b, c.a)
+  else
+    local c = actionNotUsableColor
+		f.icon:SetVertexColor(c.r, c.g, c.b, c.a)
+		f.normalTexture:SetVertexColor(1.0, 1.0, 1.0)
+	end
+end
+
+function ReActionButton.prototype:UpdateCooldown()
+  local action = self:GetActionID()
+  if action then
+  	local start, duration, enable = GetActionCooldown(self:GetActionID())
+  	CooldownFrame_SetTimer(self.frames.cooldown, start, duration, enable)
+    -- do numeric cooldown stuff here
+  end
+end
+
+function ReActionButton.prototype:UpdateFlash()
+  local b = self.button
+  local action = self:GetActionID()
+	if action and ((IsAttackAction(action) and IsCurrentAction(action)) or IsAutoRepeatAction(action)) then
+    self:StartFlash()
+	else
+    self:StopFlash()
+	end
+end
+
+function ReActionButton.prototype:UpdateVisibility()
+  local action = self:GetActionID()
+  local b = self.button
+
+  if b:GetAttribute("statehidden") then
+    b:Hide()
+  elseif action and HasAction(action) then
+    b:GetNormalTexture():SetAlpha(1.0)
+    b:Show()
+  elseif self.showGrid > 0 then
+    b:GetNormalTexture():SetAlpha(0.5)
+    self.frames.cooldown:Hide()
+    b:Show()
+  else
+    b:Hide()
+  end
+end
+
+function ReActionButton.prototype:UpdateEvents()
+  local action = self:GetActionID()
+	if action and HasAction(action) then
+    self:RegisterActionEvents()
+  elseif self.actionEventsRegistered then
+    self:UnregisterActionEvents()
+	end
+end
+
+function ReActionButton.prototype:UpdateTooltip()
+  local action = self:GetActionID()
+	if action and GameTooltip:SetAction(action) then
+		self.tooltipTime = TOOLTIP_UPDATE_TIME
+	else
+		self.tooltipTime = nil
+	end
+end
+
+
+