--[[ $Id: AceGUIWidget-DropDown-Items.lua 916 2010-03-15 12:24:36Z nevcairiel $ ]]
--

local AceGUI = LibStub('AceGUI-3.0')

-- Lua APIs
local select, assert = select, assert

-- WoW APIs
local PlaySound = PlaySound
local CreateFrame = CreateFrame

local function fixlevels(parent, ...)
  local i = 1
  local child = select(i, ...)
  while child do
    child:SetFrameLevel(parent:GetFrameLevel() + 1)
    fixlevels(child, child:GetChildren())
    i = i + 1
    child = select(i, ...)
  end
end

local function fixstrata(strata, parent, ...)
  local i = 1
  local child = select(i, ...)
  parent:SetFrameStrata(strata)
  while child do
    fixstrata(strata, child, child:GetChildren())
    i = i + 1
    child = select(i, ...)
  end
end

-- ItemBase is the base "class" for all dropdown items.
-- Each item has to use ItemBase.Create(widgetType) to
-- create an initial 'self' value.
-- ItemBase will add common functions and ui event handlers.
-- Be sure to keep basic usage when you override functions.

local ItemBase = {
  -- NOTE: The ItemBase version is added to each item's version number
  --       to ensure proper updates on ItemBase changes.
  --       Use at least 1000er steps.
  version = 1000,
  counter = 0,
}

function ItemBase.Frame_OnEnter(this)
  local self = this.obj

  if self.useHighlight then
    self.highlight:Show()
  end
  self:Fire('OnEnter')

  if self.specialOnEnter then
    self.specialOnEnter(self)
  end
end

function ItemBase.Frame_OnLeave(this)
  local self = this.obj

  self.highlight:Hide()
  self:Fire('OnLeave')

  if self.specialOnLeave then
    self.specialOnLeave(self)
  end
end

-- exported, AceGUI callback
function ItemBase.OnAcquire(self)
  self.frame:SetToplevel(true)
  self.frame:SetFrameStrata('FULLSCREEN_DIALOG')
end

-- exported, AceGUI callback
function ItemBase.OnRelease(self)
  self:SetDisabled(false)
  self.pullout = nil
  self.frame:SetParent(nil)
  self.frame:ClearAllPoints()
  self.frame:Hide()
end

-- exported
-- NOTE: this is called by a Dropdown-Pullout.
--       Do not call this method directly
function ItemBase.SetPullout(self, pullout)
  self.pullout = pullout

  self.frame:SetParent(nil)
  self.frame:SetParent(pullout.itemFrame)
  self.parent = pullout.itemFrame
  fixlevels(pullout.itemFrame, pullout.itemFrame:GetChildren())
end

-- exported
function ItemBase.SetText(self, text)
  self.text:SetText(text or '')
end

-- exported
function ItemBase.GetText(self)
  return self.text:GetText()
end

-- exported
function ItemBase.SetPoint(self, ...)
  self.frame:SetPoint(...)
end

-- exported
function ItemBase.Show(self)
  self.frame:Show()
end

-- exported
function ItemBase.Hide(self)
  self.frame:Hide()
end

-- exported
function ItemBase.SetDisabled(self, disabled)
  self.disabled = disabled
  if disabled then
    self.useHighlight = false
    self.text:SetTextColor(0.5, 0.5, 0.5)
  else
    self.useHighlight = true
    self.text:SetTextColor(1, 1, 1)
  end
end

-- exported
-- NOTE: this is called by a Dropdown-Pullout.
--       Do not call this method directly
function ItemBase.SetOnLeave(self, func)
  self.specialOnLeave = func
end

-- exported
-- NOTE: this is called by a Dropdown-Pullout.
--       Do not call this method directly
function ItemBase.SetOnEnter(self, func)
  self.specialOnEnter = func
end

function ItemBase.Create(type)
  -- NOTE: Most of the following code is copied from AceGUI-3.0/Dropdown widget
  local count = AceGUI:GetNextWidgetNum(type)
  local frame = CreateFrame('Button', 'AceGUI30DropDownItem' .. count)
  local self = {}
  self.frame = frame
  frame.obj = self
  self.type = type

  self.useHighlight = true

  frame:SetHeight(17)
  frame:SetFrameStrata('FULLSCREEN_DIALOG')

  local text = frame:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
  text:SetTextColor(1, 1, 1)
  text:SetJustifyH('LEFT')
  text:SetPoint('TOPLEFT', frame, 'TOPLEFT', 18, 0)
  text:SetPoint('BOTTOMRIGHT', frame, 'BOTTOMRIGHT', -8, 0)
  self.text = text

  local highlight = frame:CreateTexture(nil, 'OVERLAY')
  highlight:SetTexture('Interface\\QuestFrame\\UI-QuestTitleHighlight')
  highlight:SetBlendMode('ADD')
  highlight:SetHeight(14)
  highlight:ClearAllPoints()
  highlight:SetPoint('RIGHT', frame, 'RIGHT', -3, 0)
  highlight:SetPoint('LEFT', frame, 'LEFT', 5, 0)
  highlight:Hide()
  self.highlight = highlight

  local check = frame:CreateTexture('OVERLAY')
  check:SetWidth(16)
  check:SetHeight(16)
  check:SetPoint('LEFT', frame, 'LEFT', 3, -1)
  check:SetTexture('Interface\\Buttons\\UI-CheckBox-Check')
  check:Hide()
  self.check = check

  local sub = frame:CreateTexture('OVERLAY')
  sub:SetWidth(16)
  sub:SetHeight(16)
  sub:SetPoint('RIGHT', frame, 'RIGHT', -3, -1)
  sub:SetTexture('Interface\\ChatFrame\\ChatFrameExpandArrow')
  sub:Hide()
  self.sub = sub

  frame:SetScript('OnEnter', ItemBase.Frame_OnEnter)
  frame:SetScript('OnLeave', ItemBase.Frame_OnLeave)

  self.OnAcquire = ItemBase.OnAcquire
  self.OnRelease = ItemBase.OnRelease

  self.SetPullout = ItemBase.SetPullout
  self.GetText = ItemBase.GetText
  self.SetText = ItemBase.SetText
  self.SetDisabled = ItemBase.SetDisabled

  self.SetPoint = ItemBase.SetPoint
  self.Show = ItemBase.Show
  self.Hide = ItemBase.Hide

  self.SetOnLeave = ItemBase.SetOnLeave
  self.SetOnEnter = ItemBase.SetOnEnter

  return self
end

--[[
	Template for items:
	
-- Item:
--
do
	local widgetType = "Dropdown-Item-"
	local widgetVersion = 1
	
	local function Constructor()
		local self = ItemBase.Create(widgetType)
		
		AceGUI:RegisterAsWidget(self)
		return self
	end
	
	AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end
--]]

-- Item: Header
-- A single text entry.
-- Special: Different text color and no highlight
do
  local widgetType = 'Dropdown-Item-Header'
  local widgetVersion = 1

  local function OnEnter(this)
    local self = this.obj
    self:Fire('OnEnter')

    if self.specialOnEnter then
      self.specialOnEnter(self)
    end
  end

  local function OnLeave(this)
    local self = this.obj
    self:Fire('OnLeave')

    if self.specialOnLeave then
      self.specialOnLeave(self)
    end
  end

  -- exported, override
  local function SetDisabled(self, disabled)
    ItemBase.SetDisabled(self, disabled)
    if not disabled then
      self.text:SetTextColor(1, 1, 0)
    end
  end

  local function Constructor()
    local self = ItemBase.Create(widgetType)

    self.SetDisabled = SetDisabled

    self.frame:SetScript('OnEnter', OnEnter)
    self.frame:SetScript('OnLeave', OnLeave)

    self.text:SetTextColor(1, 1, 0)

    AceGUI:RegisterAsWidget(self)
    return self
  end

  AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end

-- Item: Execute
-- A simple button
do
  local widgetType = 'Dropdown-Item-Execute'
  local widgetVersion = 1

  local function Frame_OnClick(this, button)
    local self = this.obj
    if self.disabled then
      return
    end
    self:Fire('OnClick')
    if self.pullout then
      self.pullout:Close()
    end
  end

  local function Constructor()
    local self = ItemBase.Create(widgetType)

    self.frame:SetScript('OnClick', Frame_OnClick)

    AceGUI:RegisterAsWidget(self)
    return self
  end

  AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end

-- Item: Toggle
-- Some sort of checkbox for dropdown menus.
-- Does not close the pullout on click.
do
  local widgetType = 'Dropdown-Item-Toggle'
  local widgetVersion = 3

  local function UpdateToggle(self)
    if self.value then
      self.check:Show()
    else
      self.check:Hide()
    end
  end

  local function OnRelease(self)
    ItemBase.OnRelease(self)
    self:SetValue(nil)
  end

  local function Frame_OnClick(this, button)
    local self = this.obj
    if self.disabled then
      return
    end
    self.value = not self.value
    if self.value then
      PlaySound('igMainMenuOptionCheckBoxOn')
    else
      PlaySound('igMainMenuOptionCheckBoxOff')
    end
    UpdateToggle(self)
    self:Fire('OnValueChanged', self.value)
  end

  -- exported
  local function SetValue(self, value)
    self.value = value
    UpdateToggle(self)
  end

  -- exported
  local function GetValue(self)
    return self.value
  end

  local function Constructor()
    local self = ItemBase.Create(widgetType)

    self.frame:SetScript('OnClick', Frame_OnClick)

    self.SetValue = SetValue
    self.GetValue = GetValue
    self.OnRelease = OnRelease

    AceGUI:RegisterAsWidget(self)
    return self
  end

  AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end

-- Item: Menu
-- Shows a submenu on mouse over
-- Does not close the pullout on click
do
  local widgetType = 'Dropdown-Item-Menu'
  local widgetVersion = 2

  local function OnEnter(this)
    local self = this.obj
    self:Fire('OnEnter')

    if self.specialOnEnter then
      self.specialOnEnter(self)
    end

    self.highlight:Show()

    if not self.disabled and self.submenu then
      self.submenu:Open(
        'TOPLEFT',
        self.frame,
        'TOPRIGHT',
        self.pullout:GetRightBorderWidth(),
        0,
        self.frame:GetFrameLevel() + 100
      )
    end
  end

  local function OnHide(this)
    local self = this.obj
    if self.submenu then
      self.submenu:Close()
    end
  end

  -- exported
  local function SetMenu(self, menu)
    assert(menu.type == 'Dropdown-Pullout')
    self.submenu = menu
  end

  -- exported
  local function CloseMenu(self)
    self.submenu:Close()
  end

  local function Constructor()
    local self = ItemBase.Create(widgetType)

    self.sub:Show()

    self.frame:SetScript('OnEnter', OnEnter)
    self.frame:SetScript('OnHide', OnHide)

    self.SetMenu = SetMenu
    self.CloseMenu = CloseMenu

    AceGUI:RegisterAsWidget(self)
    return self
  end

  AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end

-- Item: Separator
-- A single line to separate items
do
  local widgetType = 'Dropdown-Item-Separator'
  local widgetVersion = 1

  -- exported, override
  local function SetDisabled(self, disabled)
    ItemBase.SetDisabled(self, disabled)
    self.useHighlight = false
  end

  local function Constructor()
    local self = ItemBase.Create(widgetType)

    self.SetDisabled = SetDisabled

    local line = self.frame:CreateTexture(nil, 'OVERLAY')
    line:SetHeight(1)
    line:SetTexture(0.5, 0.5, 0.5)
    line:SetPoint('LEFT', self.frame, 'LEFT', 10, 0)
    line:SetPoint('RIGHT', self.frame, 'RIGHT', -10, 0)

    self.text:Hide()

    self.useHighlight = false

    AceGUI:RegisterAsWidget(self)
    return self
  end

  AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
end
