view classes/BagButton.lua @ 174:09f7af2f53f8

Pretty totem bar textures
author Flick <flickerstreak@gmail.com>
date Wed, 20 Oct 2010 00:41:10 +0000
parents 8cc187143acd
children df68b5a40490
line wrap: on
line source
local ReAction = ReAction
local L = ReAction.L
local _G = _G
local CreateFrame = CreateFrame
local format = string.format
local GetCVar = GetCVar
local ContainerIDToInventoryID = ContainerIDToInventoryID
local NUM_CONTAINER_FRAMES = NUM_CONTAINER_FRAMES
local IsModifiedClick = IsModifiedClick
local CursorHasItem = CursorHasItem
local GetInventoryItemTexture = GetInventoryItemTexture
local GetInventorySlotInfo = GetInventorySlotInfo
local PickupBagFromSlot = PickupBagFromSlot
local CursorCanGoInSlot = CursorCanGoInSlot

-- class declarations
local Super    = ReAction.Button
local BagBase  = setmetatable( { }, { __index = Super } )
local Bag      = setmetatable( { }, { __index = BagBase } )
local Backpack = setmetatable( { }, { __index = BagBase } )
local Keyring  = setmetatable( { }, { __index = BagBase } )

ReAction.Button.Bag = BagBase

--
-- Bag Button base class
--

function BagBase:New( idx, moduleConfig, bar, idHint )
  local name = format("ReAction_%s_Bag_%d",bar:GetName(),idx)

  -- use a variable private leaf implementation class
  -- unlike traditional OO programming, we can initialize the leaf
  -- class before initializing its derived class
  local class = Bag
  if idx == 1 then
    class = Backpack
  elseif idx == 6 then
    class = Keyring
  end
  self = class:New(name,moduleConfig.buttons[bar:GetName()][idx], bar, idx)
  self.moduleConfig = moduleConfig

  local f = self:GetFrame()
  local config = self:GetConfig()

  -- set up the bag ID pool
  self:SetActionIDPool("bag",6)
  config.bagID = self:AcquireActionID(config.bagID, idHint, true)

  -- non secure scripts
  f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end)
  f:SetScript("OnEnter", function(frame) self:OnEnter() end)
  f:SetScript("OnLeave", function(frame) self:OnLeave() end)
  f:SetScript("OnReceiveDrag", function(frame, ...) self:OnReceiveDrag(...) end)
  f:SetScript("OnClick", function(frame, ...) self:OnClick(...) end)

  -- secure handlers
  -- (none)

  -- event registration
  f:EnableMouse(true)
  f:RegisterForClicks("LeftButtonUp","RightButtonUp")
  f:RegisterEvent("UPDATE_BINDINGS")

  -- frame setup
  f:SetID(self:GetBagID())

  if not f.hotkey then
    local h = f:CreateFontString(name.."HotKey","ARTWORK","NumberFontNormalSmallGray")
    h:SetWidth(30)
    h:SetHeight(10)
    h:SetJustifyH("RIGHT")
    h:SetPoint("TOPLEFT",f,"TOPLEFT",-2,-2)
    h:Show()
    f.hotkey = h
  end

  if not _G[name.."ItemAnim"] then
    local anim = CreateFrame("Model",name.."ItemAnim",f,"ItemAnimTemplate")
    anim:SetPoint("BOTTOMRIGHT",f,"BOTTOMRIGHT",-10,0)
    anim:Hide()
  end

  if not f.border then
    local b = f:CreateTexture(name.."Border","OVERLAY")
    b:SetAllPoints()
    b:SetWidth(f:GetWidth()*(62/36))
    b:SetHeight(f:GetHeight()*(62/36))
    b:SetTexture("Interface\\Buttons\UI-ActionButton-Border")
    b:SetBlendMode("ADD")
    b:Hide()
    f.border = b
  end

  self.frames.count:SetDrawLayer("ARTWORK")

  self.frames.hotkey = f.hotkey
  self.frames.border = _G[name.."Border"]
  self.frames.icon = _G[name.."IconTexture"]
  self.frames.anim = _G[name.."ItemAnim"]

  -- initial display
  if ReAction:GetConfigMode() then
    self:GetFrame():Show()
  end

  self:Refresh()

  return self
end

function BagBase:GetModuleConfig()
  -- this is the Bag module config structure,
  -- not the config structure of the bar itself
  return self.moduleConfig
end

function BagBase:GetActionID()
  return self.config.bagID
end

function BagBase:GetBagID()
  return self:GetActionID() - 1
end

function BagBase:Refresh()
  Super.Refresh(self)
  self:UpdateHotkey()
  self:Update()
end

function BagBase:Update()
  self:UpdateChecked()
end

function BagBase:UpdateChecked(force)
  if force == nil then
    for i=1, NUM_CONTAINER_FRAMES do
      local c = _G["ContainerFrame"..i]
      if c:GetID() == self:GetBagID() and c:IsShown() then
        self:GetFrame():SetChecked(1)
        return
      end
    end
    self:GetFrame():SetChecked(0)
  end
  self:GetFrame():SetChecked(force)
end

function BagBase:OnEvent(evt, ...)
  if self[evt] then
    self[evt](self, ...)
  end
end

function BagBase:OnEnter()
  self:SetTooltip()
end

function BagBase:OnLeave()
  GameTooltip:Hide()
end

function BagBase:UPDATE_BINDINGS()
  self:UpdateHotkey()
end


--
-- Bag Button class
--
function Bag:New(name, cfg, bar, idx)
  self = Super.New(self, name, cfg, bar, idx, "ItemButtonTemplate" )

  local f = self:GetFrame()

  f:SetCheckedTexture("Interface\\Buttons\\CheckButtonHilight")

  f:RegisterEvent("CURSOR_UPDATE")
  f:RegisterEvent("BAG_UPDATE")
  f:RegisterEvent("BAG_CLOSED")
  f:SetScript("OnDragStart", function(frame, ...) self:OnDragStart(...) end)
  f:RegisterForDrag("LeftButton")

  -- attach to skinner
  bar:SkinButton(self,
    {
      Icon = _G[name.."IconTexture"]
    }
  )

  return self
end

function Bag:GetInventorySlot()
  return ContainerIDToInventoryID(self:GetBagID())
end

function Bag:GetInventorySlotName()
  return "Bag"..(self:GetBagID()-1).."Slot"
end

function Bag:SetTooltip()
  GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_LEFT")
  if not GameTooltip:SetInventoryItem("player", self:GetInventorySlot()) then
    GameTooltip:SetText(EQUIP_CONTAINER, 1.0, 1.0, 1.0)
  end
end

function Bag:Update()
	local texture = GetInventoryItemTexture("player", self:GetInventorySlot())
	if texture then
    self.frames.icon:SetTexture(texture)
    self.frames.icon:Show()
    self:GetFrame():SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
	else
    local _, bgTex = GetInventorySlotInfo(self:GetInventorySlotName())
    self.frames.icon:SetTexture(bgTex)
    self:GetFrame():SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
	end
  self:UpdateChecked()
end

function Bag:OnClick()
  if IsModifiedClick("OPENALLBAGS") then
    OpenAllBags()
  else
    if not PutItemInBag(self:GetInventorySlot()) then
      ToggleBag(self:GetBagID())
    end
  end
  self:UpdateChecked()
end

function Bag:OnReceiveDrag()
  if CursorHasItem() then
    PutItemInBag(self:GetInventorySlot())
  end
end

function Bag:OnDragStart()
  PickupBagFromSlot(self:GetInventorySlot())
  self:Update()
end

function Bag:BAG_UPDATE(bag)
  if bag == self:GetBagID() then
    self:Update()
  end
end

function Bag:CURSOR_UPDATE()
  if CursorCanGoInSlot(self:GetInventorySlot()) then
    self:GetFrame():LockHighlight()
  else
    self:GetFrame():UnlockHighlight()
  end
end

function Bag:BAG_CLOSED(bag)
  if bag == self:GetBagID() then
    self:Update()
  end
end


--
-- Backpack Button class
--
function Backpack:New(name, cfg, bar, idx)
  self = Super.New(self, name, cfg, bar, idx, "ItemButtonTemplate" )

  local f = self:GetFrame()
  local icon = _G[name.."IconTexture"]
  icon:SetTexture("Interface\\Buttons\\Button-Backpack-Up")
  icon:Show()
  f:SetCheckedTexture("Interface\\Buttons\\CheckButtonHilight")
  f:RegisterEvent("PLAYER_ENTERING_WORLD");
  f:RegisterEvent("CVAR_UPDATE");
  f:SetScript("OnShow", function(frame, ...) self:OnShow(...) end)

  -- attach to skinner
  bar:SkinButton(self,
    {
      Icon = _G[name.."IconTexture"]
    }
  )

  return self
end

function Backpack:Update()
  self:UpdateFreeSlots()
  self:UpdateChecked()
end

function Backpack:UpdateFreeSlots()
  if GetCVar("displayFreeBagSlots") == "1" then
    local total = 0
    for i = BACKPACK_CONTAINER, NUM_BAG_SLOTS do
      local free, family = GetContainerNumFreeSlots(i)
      if family == 0 then
        total = total + free
      end
    end

    self.freeSlots = total
    self.frames.count:SetText(format("(%s)", self.freeSlots))
    self.frames.count:Show()
  elseif self.frames.count:IsShown() then
    self.frames.count:Hide()
  end
end

function Backpack:SetTooltip()
  GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_LEFT")
  GameTooltip:SetText(BACKPACK_TOOLTIP, 1.0, 1.0, 1.0)
  GameTooltip:AddLine(string.format(NUM_FREE_SLOTS, (self.freeSlots or 0)))
  GameTooltip:Show();
end

function Backpack:OnShow()
  self:UpdateFreeSlots()
end

function Backpack:OnClick()
  if IsModifiedClick("OPENALLBAGS") then
    OpenAllBags()
  else
    if not PutItemInBackpack() then
      ToggleBackpack()
    end
  end
  self:UpdateChecked()
end

function Backpack:OnReceiveDrag()
  if CursorHasItem() then
    PutItemInBackpack()
  end
end

function Backpack:PLAYER_ENTERING_WORLD()
  self:CVAR_UPDATE("DISPLAY_FREE_BAG_SLOTS", GetCVar("displayFreeBagSlots"))
end

function Backpack:CVAR_UPDATE( cvar, value )
  if cvar == "DISPLAY_FREE_BAG_SLOTS" then
    if value == "1" then
      self:GetFrame():RegisterEvent("BAG_UPDATE")
    else
      self:GetFrame():UnregisterEvent("BAG_UPDATE")
    end
    self:UpdateFreeSlots()
  end
end

function Backpack:BAG_UPDATE(bag)
  if bag >= BACKPACK_CONTAINER and bag <= NUM_BAG_SLOTS then
    self:UpdateFreeSlots()
  end
end


--
-- Keyring Button class
--
function Keyring:New(name, cfg, bar, idx)
  self = Super.New(self, name, cfg, bar, idx, "ItemButtonTemplate" )

  local f = self:GetFrame()

  f:SetWidth(18)
  f:SetHeight(39)

  local tex = f:GetNormalTexture()
  tex:ClearAllPoints()
  tex:SetAllPoints()
  
  f:SetNormalTexture("Interface\\Buttons\\UI-Button-KeyRing")
  f:SetHighlightTexture("Interface\\Buttons\\UI-Button-KeyRing-Highlight")
  f:SetPushedTexture("Interface\\Buttons\\UI-Button-KeyRing-Down")
  f:GetNormalTexture():SetTexCoord(0,0.5625,0,0.609375)
  f:GetHighlightTexture():SetTexCoord(0,0.5625,0,0.609375)
  f:GetPushedTexture():SetTexCoord(0,0.5625,0,0.609375)

  if not HasKey() then
    f:Hide()
  end

  -- DO NOT attach to skinner

  return self
end

function Keyring:GetBagID()
  return KEYRING_CONTAINER
end

function Keyring:Refresh()
  local f = self:GetFrame()
  self.bar:PlaceButton( self, f:GetHeight(), f:GetHeight() ) -- use height x height since it's an odd size
  self:UpdateHotkey()
  self:Update()
end

function Keyring:SetTooltip()
  GameTooltip:SetOwner(self:GetFrame(), "ANCHOR_RIGHT");
  GameTooltip:SetText(KEYRING, HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);
  GameTooltip:AddLine();
end

function Keyring:OnReceiveDrag()
  if CursorHasItem() then
    PutKeyInKeyRing()
  end
end

function Keyring:OnClick()
  if CursorHasItem() then
    PutKeyInKeyRing()
  else
    ToggleKeyRing()
  end
  self:UpdateChecked()
end

function Keyring:ShowGridTemp(show)
  if not HasKey() then
    if show then 
      self:GetFrame():Show()
    else
      self:GetFrame():Hide()
    end
  end
end