--[[
Copyright (c) 2006, Hendrik Leppkes < mail@nevcairiel.net >
All rights reserved.

Redistribution and use in source and binary forms, with or without 
modification, are permitted provided that the following conditions are 
met:

    * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above 
       copyright notice, this list of conditions and the following 
       disclaimer in the documentation and/or other materials provided 
       with the distribution.
    * Neither the name of the Bartender3 Development Team nor the names of 
       its contributors may be used to endorse or promote products derived 
       from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
]]
--[[ $Id: Bartender3_BarClass.lua 36970 2007-05-26 10:48:00Z nevcairiel $ ]]
local Bartender3 = Bartender3

local VERSION = tonumber(("$Revision: 36970 $"):match("%d+"))
if Bartender3.revision < VERSION then
	Bartender3.version = Bartender3.versionstring:format(VERSION)
	Bartender3.revision = VERSION
	Bartender3.date = ('$Date: 2007-05-26 06:48:00 -0400 (Sat, 26 May 2007) $'):match('%d%d%d%d%-%d%d%-%d%d')
end

local AceOO = AceLibrary("AceOO-2.0")
local dewdrop = AceLibrary("Dewdrop-2.0")

local L = AceLibrary("AceLocale-2.2"):new("Bartender3")

Bartender3.statemodifiers = { "ctrl", "shift", "alt" }

if not Bartender3.Class then Bartender3.Class = {} end
Bartender3.Class.Bar = AceOO.Class("AceEvent-2.0")
Bartender3.Class.ActionBar = AceOO.Class(Bartender3.Class.Bar)
Bartender3.Class.SpecialBar = AceOO.Class(Bartender3.Class.Bar, "AceHook-2.1")

local _G = getfenv(0)

local table_insert = table.insert
local table_remove = table.remove
local math_floor = math.floor

local function onUpdateFunc(bar, elapsed) 
	local self = bar.class
	self.elapsed = self.elapsed + elapsed
	if self.elapsed > 0.2 then
		self:OnUpdate(self.elapsed)
		self.elapsed = 0
	end
end

function Bartender3.Class.Bar.prototype:init(id, config, statebar)
	Bartender3.Class.Bar.super.prototype.init(self)
	self.id = id
	self.config = config
	self.statebar = statebar
	self.barname = L["Bar %s"]:format(self.id)
	if self.statebar and self.id == 1 then self.mainbar = true end
	
	self:CreateBarFrame()
	
	table_insert(Bartender3.bars, self)
	
end

function Bartender3.Class.Bar.prototype:ChangeProfile(config)
	self.config = config
end

function Bartender3.Class.Bar.prototype:CreateBarFrame()
	local name = "BT3Bar"..self.id
	local frame = CreateFrame("Button", name, UIParent, self.statebar and "SecureStateDriverTemplate")
	frame.class = self
	frame:EnableMouse(false)
	frame:SetMovable(true)
	--frame:SetClampedToScreen(true)
	frame:RegisterForDrag("LeftButton")
	frame:RegisterForClicks("RightButtonDown", "LeftButtonUp")
	frame:SetWidth(10)
	frame:SetHeight(10)
	frame:SetBackdrop({bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16, edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", edgeSize = 16, insets = {left = 5, right = 3, top = 3, bottom = 5},})
	frame:SetBackdropColor(0, 0, 0, 0)
	frame:SetBackdropBorderColor(0.5, 0.5, 0, 0)
	frame:ClearAllPoints()
	frame:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
	frame.Text = frame:CreateFontString(nil, "ARTWORK")
	frame.Text:SetFontObject(GameFontNormal)
	frame.Text:SetText()
	frame.Text:Show()
	frame.Text:ClearAllPoints()
	frame.Text:SetPoint("CENTER", frame, "CENTER",0,0)
	if self.config.Hide then frame:Hide() else frame:Show() end
	self.frame = frame
	
	self.elapsed = 0
	if self.config.FadeOut then frame:SetScript("OnUpdate", onUpdateFunc ) end
end

function Bartender3.Class.Bar.prototype:OnUpdate(elapsed)
	if self.config.FadeOut then
		if MouseIsOver(self.frame) and self.faded then
			self.frame:SetAlpha(self.config.Alpha)
			self.faded = nil
			if self.buttonobjects then
				for k,v in pairs(self.buttonobjects) do
					v:UpdateCooldown()
				end
			end
		elseif not MouseIsOver(self.frame) and not self.faded then
			self.frame:SetAlpha(0)
			self.faded = true
			for k,v in pairs(self.buttons) do
				if v.cooldown then v.cooldown:Hide() end
			end
		end
	end
end

function Bartender3.Class.Bar.prototype:SetFadeOut(fade)
	self.config.FadeOut = fade
	self.faded = nil
	if not fade then
		self.frame:SetAlpha(self.config.Alpha)
		self.frame:SetScript("OnUpdate", nil)
	else
		self.frame:SetScript("OnUpdate", onUpdateFunc)
	end
end

local function onEnterFunc(bar)
	bar:SetBackdropBorderColor(0.5, 0.5, 0, 1)
end

local function onLeaveFunc(bar)
	bar:SetBackdropBorderColor(0, 0, 0, 0)
end

local function onDragStartFunc(bar)
	if Bartender3.db.profile.Sticky and StickyFrames then
		local frames = {}
		for k,v in pairs(Bartender3.bars) do
			if v.frame ~= bar then table_insert(frames, v.frame) end
		end
		local p = 8 - bar.class.config.Padding
		StickyFrames:StartMoving(bar, frames, p, p, p, p)
	else
		bar:StartMoving()
	end
	bar:SetBackdropBorderColor(0, 0, 0, 0)
end

local function onDragStopFunc(bar)
	local self = bar.class
	if Bartender3.db.profile.Sticky and StickyFrames then
		StickyFrames:StopMoving(bar)
	else
		bar:StopMovingOrSizing()
	end
	self:SavePosition()
end

local function onClickFunc(bar, button, down)
	local self = bar.class
	if button == "RightButton" then
		self:ShowBarOptions()
	elseif button == "LeftButton" then
		self:ToggleVisibilty()
	end
end

function Bartender3.Class.Bar.prototype:UnlockFrames()
	local frame = self.frame
	frame:EnableMouse(true)
	frame:SetScript("OnEnter", onEnterFunc)
	frame:SetScript("OnLeave", onLeaveFunc)
	frame:SetScript("OnDragStart", onDragStartFunc)
	frame:SetScript("OnDragStop", onDragStopFunc)
	frame:SetScript("OnClick", onClickFunc)
	if self.config.Hide then
		frame:SetBackdropColor(1, 0, 0, 0.5)
	else
		frame:SetBackdropColor(0, 1, 0, 0.5)
	end
	frame:SetFrameLevel(3)
	frame.Text:SetText(self.barname)
	frame:Show()
	if self.config.FadeOut then
		frame:SetScript("OnUpdate", nil)
		frame:SetAlpha(self.config.Alpha)
		self.faded = nil
	end
end

function Bartender3.Class.Bar.prototype:LockFrames()
	local frame = self.frame
	onDragStopFunc(frame)
	frame:EnableMouse(false)
	frame:SetScript("OnEnter", nil)
	frame:SetScript("OnLeave", nil)
	frame:SetScript("OnDragStart", nil)
	frame:SetScript("OnDragStop", nil)
	frame:SetScript("OnClick", nil)
	frame:SetBackdropColor(0, 0, 0, 0)
	frame:SetBackdropBorderColor(0, 0, 0, 0)
	frame.Text:SetText("")
	--frame:SetFrameLevel(1)
	if self.config.Hide then self.frame:Hide() else self.frame:Show() end
	if self.config.FadeOut then
		frame:SetScript("OnUpdate", onUpdateFunc)
	end
end

-- This function will not work in combat
function Bartender3.Class.Bar.prototype:ToggleVisibilty()
	if InCombatLockdown() then return end -- to avoid a message, you never know
	self.config.Hide = not self.config.Hide
	if self.config.Hide and Bartender3.unlock then
		self.frame:SetBackdropColor(1, 0, 0, 0.5)
	elseif self.config.Hide then
		self.frame:Hide()
	elseif Bartender3.unlock then
		self.frame:SetBackdropColor(0, 1, 0, 0.5)
	else
		self.frame:Show()
	end
end

function Bartender3.Class.Bar.prototype:RefreshLayout()
	if InCombatLockdown() then return end -- to avoid a message, you never know
	self:RefreshScale()
	self:RefreshButtonLayout()
	self:RefreshAlpha()
	self:LoadPosition()
	if self.config.Hide and not Bartender3.unlock and self.config.Enabled then self.frame:Hide() else self.frame:Show() end
end

function Bartender3.Class.Bar.prototype:LoadPosition()
	local x, y, s = self.config.PosX, self.config.PosY, self.frame:GetEffectiveScale()
	local defaultx, defaulty, defaultanchor = (Bartender3.defaultpositions[self.id].PosX) or 0, (Bartender3.defaultpositions[self.id].PosY) or 0, Bartender3.defaultpositions[self.id].Anchor or "BOTTOMLEFT"
	if x and y then
		x,y = x/s, y/s
	end
	self.frame:ClearAllPoints()
	self.frame:SetPoint("BOTTOMLEFT", UIParent, x and "BOTTOMLEFT" or defaultanchor, x or defaultx, y or defaulty)
end

function Bartender3.Class.Bar.prototype:SavePosition()
	local frame = self.frame
	local x,y = frame:GetLeft(), frame:GetBottom()
	local s = frame:GetEffectiveScale()
	x,y = x*s,y*s
	self.config.PosX = x
	self.config.PosY = y
end

function Bartender3.Class.Bar.prototype:RefreshButtonLayout()
	local buttons = #self.buttons
	local Rows = self.config.Rows or 1
	local ButtonPerRow = math_floor(buttons / Rows + 0.5) -- just a precaution
	Rows = math_floor(buttons / ButtonPerRow + 0.5)
	local Padding = self.config.Padding or 0
	self.frame:SetWidth(self.buttonwidth * ButtonPerRow + ((ButtonPerRow - 1) * Padding) + 8)
	self.frame:SetHeight(self.buttonheight * Rows + ((Rows - 1) * Padding) + 8)
	for i=1,buttons do
		local button = self.buttons[i]
		button:ClearAllPoints()
		if i > 1 and ((i-1) % ButtonPerRow) == 0 then
			button:SetPoint("TOPLEFT", self.buttons[i-ButtonPerRow], "BOTTOMLEFT", 0, self.specialmicromenu and -(Padding - 21) or -Padding)
		elseif i > 1 then
			button:SetPoint("TOPLEFT", self.buttons[i-1], "TOPRIGHT", Padding, 0)
		else
			button:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 5, self.specialmicromenu and 18 or -3)
		end
	end
end

function Bartender3.Class.Bar.prototype:RefreshStyle()
	local style = self.config.Style
	for i,v in pairs(self.buttons) do
		Bartender3:RefreshStyle(v, self)
	end
end

function Bartender3.Class.Bar.prototype:RefreshScale()
	self.frame:SetScale(self.config.Scale or 1)
	self:LoadPosition()
end

function Bartender3.Class.Bar.prototype:RefreshAlpha()
	for i,v in pairs(self.buttons) do
		v:SetAlpha(self.config.Alpha or 0)
	end
end

function Bartender3.Class.Bar.prototype:InitOptions()
	self.optionstable = Bartender3:CreateBarOptions(self.id, self.barname, not self.statebar)
	if self.optionstable.args.rows then self.optionstable.args.rows.max = ( #self.buttons > 1 ) and #self.buttons or 2 end
end

-- config functions

function Bartender3.Class.Bar.prototype:SetRows(r)
	local maxbuttons = #self.buttons
	self.config.Rows = r
	self:RefreshButtonLayout()
end

function Bartender3.Class.Bar.prototype:SetPadding(r)
	self.config.Padding = r
	self:RefreshButtonLayout()
end

function Bartender3.Class.Bar.prototype:SetScale(s)
	self.config.Scale = s
	self:RefreshScale()
end

function Bartender3.Class.Bar.prototype:SetAlpha(a)
	self.config.Alpha = a
	self:RefreshAlpha()
end

function Bartender3.Class.Bar.prototype:SetStyle(s)
	self.config.Style = s
	self:RefreshStyle()
end

function Bartender3.Class.Bar.prototype:SetShowGrid(s)
	self.config.ShowGrid = s
	for i,v in pairs(self.buttonobjects) do
		if s then
			v:ShowGrid(true)
		else
			v:HideGrid(true)
		end
	end
end

function Bartender3.Class.Bar.prototype:ShowBarOptions()
	if InCombatLockdown() then return end
	dewdrop:Open(self.frame, 'children', function() dewdrop:FeedAceOptionsTable(self.optionstable) end, 'cursorX', true, 'cursorY', true)
end

--[[
	Action Bars
	
	ActionBar is the abstract class for all of the 10 actionbars
	self.buttons holds the actual frames
	self.buttonobjects holds the ButtonClass objects
]]

function Bartender3.Class.ActionBar.prototype:init(id, config, numbuttons)
	Bartender3.Class.ActionBar.super.prototype.init(self, id, config, true)
	self.buttonwidth = 36
	self.buttonheight = 36

	self.numbuttons = numbuttons
	self:CreateButtons()
	
	self:InitStates()
	self:InitOptions()
	
	self:RefreshStyle()
	self:UpdateSelfCast()
	self:RefreshLayout()
end

function Bartender3.Class.ActionBar.prototype:ChangeProfile(config)
	Bartender3.Class.ActionBar.super.prototype.ChangeProfile(self, config)
	
	self.numbuttons = self.config.Buttons
	self:SetButtons(self.numbuttons)
	self:InitStates()
	self:RefreshLayout()
end

function Bartender3.Class.ActionBar.prototype:CreateButtons()
	if self.buttons or self.buttonobjects then return end
	self.buttons, self.buttonobjects, self.keybindings = {}, {}, {}
	for i=1, self.numbuttons do
		local button = Bartender3:GetFreeButton(self)
		table_insert(self.buttons, button.frame)
		table_insert(self.buttonobjects, button)
	end
end

function Bartender3.Class.ActionBar.prototype:SetButtons(a)
	local oldbuttons = self.numbuttons
	self.numbuttons = a
	self.config.Buttons = a
	if a > oldbuttons then
		for i=(oldbuttons+1),a do
			local button = Bartender3:GetFreeButton(self)
			table_insert(self.buttons, button.frame)
			table_insert(self.buttonobjects, button)
			if Bartender3.unlock then button.frame:SetFrameLevel(2) end
		end
		self:UpdateStates()
	elseif a < oldbuttons then
		for i=(a+1), oldbuttons do
			-- fetch the last button
			local butnum = #self.buttonobjects
			-- release it
			self.buttonobjects[butnum]:ReleaseButton()
			table_remove(self.buttons)
			table_remove(self.buttonobjects)
		end
	else return end -- no change
	local maxbuttons = #self.buttons
	self.optionstable.args.rows.max = ( maxbuttons > 1 ) and maxbuttons or 2
	-- refresh rows config.
	if self.config.Rows > maxbuttons then self:SetRows(maxbuttons) else self:SetRows(self.config.Rows) end
	self:RefreshLayout()
	self:UpdateSelfCast()
end

function Bartender3.Class.ActionBar.prototype:RefreshLayout()
	Bartender3.Class.ActionBar.super.prototype.RefreshLayout(self)
	for i,v in pairs(self.buttonobjects) do
		v:UpdateButton()
	end
end

function Bartender3.Class.ActionBar.prototype:AddRightClickState(state)
	local scrc = Bartender3.db.profile.SelfCastRightClick
	local target = scrc and "player" or nil
	
	self.frame:SetAttribute("unit-S" .. state .. "2", target)
end

function Bartender3.Class.ActionBar.prototype:UpdateSelfCast()
	for i,v in pairs(self.buttons) do
		v:SetAttribute("checkselfcast", Bartender3.db.profile.SelfCastModifier)
	end
	self:UpdateStates()
end

function Bartender3.Class.ActionBar.prototype:SetModifierState(modifier, page)
	if not self.config.States then return end
	self.config.States[modifier] = (page==0) and nil or page
	self:UpdateStates()
end

function Bartender3.Class.ActionBar.prototype:SetStancePage(stance, page)
	self.config.Stances[stance] = page
	self:UpdateStates()
end

--[[
	Special Bars
	
	Special Bars are an abstraction layer for the MicroMenu/Bags/Stance/Pet Bar
	The table self.buttons holds the actual frames of the buttons.
]]

function Bartender3.Class.SpecialBar.prototype:init(bartype, barname, config)
	Bartender3.Class.SpecialBar.super.prototype.init(self, bartype, config, false)
	self.bartype = bartype
	self.barname = barname
	self:AssignFrames(bartype)
	
	self:InitOptions()
	
	self:RefreshLayout()
	self:RefreshStyle()
end

function Bartender3.Class.SpecialBar.prototype:ChangeProfile(config)
	Bartender3.Class.ActionBar.super.prototype.ChangeProfile(self, config)
	
	self.buttons = nil
	self:AssignFrames(self.bartype)
	self:RefreshLayout()
end

function Bartender3.Class.SpecialBar.prototype:AssignFrames(bartype)
	if self.buttons then return end
	self.buttons = {}
	if not bartype then bartype = self.bartype end
	if ( bartype == "STANCE" ) then
		self.buttonwidth = ShapeshiftButton1:GetWidth()
		self.buttonheight = ShapeshiftButton1:GetHeight()
		for i=1,10 do 
			local button = _G[("ShapeshiftButton%d"):format(i)]
			button:SetParent(self.frame)
			button:SetNormalTexture("")
			
			button.icon = _G[("ShapeshiftButton%dIcon"):format(i)]
			button.cooldown = _G[("ShapeshiftButton%dCooldown"):format(i)]
			button:SetFrameLevel(2)
			table_insert(self.buttons, button) 
		end
		self:StanceBar_OnInit()
	elseif ( bartype == "PET" ) then
		self.buttonwidth = PetActionButton1:GetWidth()
		self.buttonheight = PetActionButton1:GetHeight()
		for i=1, NUM_PET_ACTION_SLOTS, 1 do
			local button = _G[("PetActionButton%d"):format(i)]
			button:SetParent(self.frame)
			button.normalTexture = _G[("PetActionButton%dNormalTexture2"):format(i)]
			button.normalTexture:Hide()
			
			button.icon = _G[("PetActionButton%dIcon"):format(i)]
			button.cooldown = _G[("PetActionButton%dCooldown"):format(i)]
			button:SetFrameLevel(2)
			table_insert(self.buttons, button) 
		end
		
		self:PetBar_OnInit()
	elseif ( bartype == "MICROMENU" ) then
		self.buttonwidth = 29
		self.buttonheight = 37
		self.specialmicromenu = true
		table_insert(self.buttons, CharacterMicroButton)
		table_insert(self.buttons, SpellbookMicroButton)
		table_insert(self.buttons, TalentMicroButton)
		UpdateTalentButton = function() end
		table_insert(self.buttons, QuestLogMicroButton)
		table_insert(self.buttons, SocialsMicroButton)
		table_insert(self.buttons, LFGMicroButton)
		table_insert(self.buttons, MainMenuMicroButton)
		table_insert(self.buttons, HelpMicroButton)
		
		for i,v in pairs(self.buttons) do v:SetParent(self.frame); v:Show(); v:SetFrameLevel(2); end
	elseif ( bartype == "BAGS" ) then
		self.buttonwidth = MainMenuBarBackpackButton:GetWidth()
		self.buttonheight = MainMenuBarBackpackButton:GetHeight()
		
		if self.config.Keyring then
			table_insert(self.buttons, KeyRingButton)
		else
			KeyRingButton:Hide()
		end
		
		if not self.config.OneBag then
			table_insert(self.buttons, CharacterBag3Slot) 
			table_insert(self.buttons, CharacterBag2Slot) 
			table_insert(self.buttons, CharacterBag1Slot) 
			table_insert(self.buttons, CharacterBag0Slot)
		else
			CharacterBag3Slot:Hide()
			CharacterBag2Slot:Hide()
			CharacterBag1Slot:Hide()
			CharacterBag0Slot:Hide()
		end
	 	--MainMenuBarBackpackButton:SetScript("OnClick", function() OpenAllBags() end)
		table_insert(self.buttons, MainMenuBarBackpackButton)
		for i,v in pairs(self.buttons) do 
			v.icon = _G[v:GetName().."IconTexture"]
			v:SetParent(self.frame)
			if v ~= KeyRingButton then v:SetNormalTexture("") end
			v:SetFrameLevel(2)
			v:Show()
		end
	elseif ( bartype == "XP" ) then
		self.buttonwidth = 1024
		self.buttonheight = 13
		table_insert(self.buttons, MainMenuExpBar)
		MainMenuExpBar:SetParent(self.frame)
		MainMenuExpBar:Show()
	end
end

function Bartender3.Class.SpecialBar.prototype:StanceBar_OnInit()
	if self.stanceinit then return end
	self.stanceinit = true
	self:SecureHook("ShapeshiftBar_Update", function() self:ShapeshiftBar_Update() end)
end

function Bartender3.Class.SpecialBar.prototype:ShapeshiftBar_Update()
	self:RefreshLayout()
	self:RefreshStyle()
end

-- maybe think about rebuilding the petbar, this hooking is a PITA
function Bartender3.Class.SpecialBar.prototype:PetBar_OnInit()
	if self.petinit then return end
	self.petinit = true
	self:SecureHook("PetActionBar_ShowGrid", function() self:PetActionBar_ShowGrid() end)
	self:SecureHook("PetActionBar_HideGrid", function() self:PetActionBar_HideGrid() end)
	self:SecureHook("PetActionBar_Update", function() self:PetActionBar_Update() end)
end

function Bartender3.Class.SpecialBar.prototype:PetActionBar_Update()
	for i, frame in pairs(self.buttons) do
		local _, _, texture = GetPetActionInfo(i);
		if ( texture ) then
			frame.normalTexture:SetTexCoord(0,0,0,0)
		else
			frame.normalTexture:SetTexCoord(-0.1,1.1,-0.1,1.12)
		end
	end
end

function Bartender3.Class.SpecialBar.prototype:PetActionBar_ShowGrid()
	local name;
	for i, frame in pairs(self.buttons) do
		name = GetPetActionInfo(i);
		if ( not name ) then
			frame.normalTexture:Show()
		end
	end
end

function Bartender3.Class.SpecialBar.prototype:PetActionBar_HideGrid()
	if ( PetActionBarFrame.showgrid == 0 ) then
		for i, frame in pairs(self.buttons) do
			frame.normalTexture:Hide()
		end
	end
end

function Bartender3.Class.SpecialBar.prototype:ToggleKeyring()
	if self.bartype ~= "BAGS" then return end
	self.config.Keyring = not self.config.Keyring
	self.buttons = nil
	self:AssignFrames(self.bartype)
	self:RefreshLayout()
	self:RefreshStyle()
end

function Bartender3.Class.SpecialBar.prototype:ToggleOneBag()
	if self.bartype ~= "BAGS" then return end
	self.config.OneBag = not self.config.OneBag
	self.buttons = nil
	self:AssignFrames(self.bartype)
	self:RefreshLayout()
	self:RefreshStyle()
	self.optionstable.args.rows.max = ( #self.buttons > 1 ) and #self.buttons or 2
end
