WoWInterface SVN mRunes

[/] [trunk/] [mRunes/] [Libs/] [LibGUIFactory-1.0/] [LibGUIFactory-1.0.lua] - Rev 8

Compare with Previous | Blame | View Log

local UIF_MAJOR, UIF_MINOR = "LibGUIFactory-1.0", 26
local UIF, oldminor = LibStub:NewLibrary(UIF_MAJOR, UIF_MINOR)
if not UIF then return end

local AceGUI = LibStub("AceGUI-3.0")
local LSM = LibStub("LibSharedMedia-3.0")

UIF.factories = UIF.factories or {}
UIF.embeds = {}

local InternalDrop, InternalButton

-- 

local function AddEmbed(name, func)
        UIF.embeds[name] = func
end

local function Embed(obj)
        for name, func in pairs(UIF.embeds) do
                obj[name] = func
        end
end

local function RecCheck(i, value, obj)
        if not obj then return end
        if type(value) == "table" then
                if (obj[i]) then
                        assert(type(obj[i]) == "table", ("%q must be a table"):format(i))
                        for subOpt, subValue in pairs(value) do
                                RecCheck(subOpt, subValue, obj[i])
                        end
                end             
        end
        if type(obj) == "table" and obj[i] then
                assert(type(obj[i]) == type(value), ("obj[%q] must be of type %s"):format(opt, type(value)))
                if type(obj[i]) == "table" then
                        obj[i] = obj[i] or value
                end
        end     
end

local function ValidateAndInsertDefaults(obj)
        assert(obj and type(obj) == "table", "The provided object to be embeded with UIF-function must be a table")
        
        -- For each in the defaults
        for opt, value in pairs(UIF.defaults) do
        
                -- If its a table
                if type(value) == "table" then
                
                        -- Check if the incomming table have this index
                        if obj[opt] then
                                
                                -- Check sp the type of the value is the same
                                assert(type(obj[opt]) == "table", ("[%q] must be a %s"):format(opt, type(value)))
                                
                                -- For each subTable do the same check
                                for subOpt, subValue in pairs(value) do                                 
                                        RecCheck(subOpt, subValue, obj[subOpt])
                                end
                        end                     
                else
                        if obj[opt] then
                                assert(type(obj[opt]) == type(value), ("obj[%q] must be of type %s"):format(opt, type(value)))
                        end                     
                end     
                
                obj[opt] = obj[opt] or value            
        end
        
        for opt, _ in pairs(obj) do
                assert(UIF.defaults[opt], ("The setting %q is not a vailid setting"):format(opt))
        end
end

function UIF:GetFactory(name, obj)
        assert(not obj or type(obj) == "table", "Invalid factory object, it must be either nil or a table")
        
        if self.factories[name] then return self.factories[name] end
        
        newObj = {}
        newObj.s = obj
        newObj.name = name
        
        ValidateAndInsertDefaults(newObj.s)             
        
        Embed(newObj)
        
        self.factories[name] = newObj
        
        return newObj
end

function UIF:UpdateFactory(name, obj)
        assert(type(obj) == "table" or not obj, "Invalid factory object, it must be either nil or a table")
        assert(self.factories[name], ("The factory %s does not exist"):format(name))
        
        ValidateAndInsertDefaults(obj)
end

local function OnMouseEnter(widget, event)
        local title, text = widget:GetUserData("enterTitle"), widget:GetUserData("enterText")
        GameTooltip:SetOwner(widget.frame)
        if title then
                GameTooltip:AddLine(title)
        end
        GameTooltip:AddLine(text)
        GameTooltip:Show()
end

local function OnMouseLeave(wdiget, event)
        GameTooltip:Hide()
end

local function SetMouseOver(self, widget, title, text)
        widget:SetUserData("enterTitle", title)
        widget:SetUserData("enterText", text)
        widget:SetCallback("OnEnter", OnMouseEnter)
        widget:SetCallback("OnLeave", OnMouseLeave)
end
AddEmbed("SetMouseOver", SetMouseOver)

----------------------
-- Changing widget Methods

-- Used for update on release widgets
local function UpdateTrigger(widget, event, ...)
        local self = widget:GetUserData("self") 
        local db = widget:GetUserData("db")
        local key = widget:GetUserData("key")
        local func = widget:GetUserData("extraCallback")
        local TriggerGlobalUpdate = widget:GetUserData("TriggerGlobalUpdate")
        
        if db then
                if select("#", ...) > 1 then
                        for i = 1, select("#", ...) do
                                db[key] = db[key] or {}
                                if type(db[key]) ~= "table" then
                                        db[key] = {}
                                end
                                db[key][i] = select(i, ...)
                        end
                else
                        if widget.min then
                                local value = ...
                                if value < widget.min then value = widget.min end
                                if value > widget.max then value = widget.max end
                                db[key] = value
                        else
                                db[key] = ...
                        end
                end
        end
        
        if widget.SetValue then
                if widget.min then
                        local value = ...
                        if value < widget.min then value = widget.min end
                        if value > widget.max then value = widget.max end
                        widget:SetValue(value)
                        if widget.editbox then
                                widget.editbox:ClearFocus()
                        end
                else
                        widget:SetValue(...)
                end
        end             
        if func then func(widget, event, ...) end
        if widget.SetColor then
                widget:SetColor(...)
        end
        if TriggerGlobalUpdate then
                if self.valuesChangedCallback then 
                        for i, func in pairs(self.valuesChangedCallback) do
                                func(self)
                        end
                end
        end
end

local function ConfirmPupup(widget, event, ...)
        if not StaticPopupDialogs["AEGUIFACTORY_CONFIRM_DIALOG"] then
                StaticPopupDialogs["AEGUIFACTORY_CONFIRM_DIALOG"] = {}
        end
        local t = StaticPopupDialogs["AEGUIFACTORY_CONFIRM_DIALOG"]
        for k in pairs(t) do
                t[k] = nil
        end
        t.text = "Are you sure?"
        t.button1 = ACCEPT
        t.button2 = CANCEL
        local data = {...}
        local dialog, oldstrata
        t.OnAccept = function()
                UpdateTrigger(widget, event, unpack(data))
                if dialog and oldstrata then
                        dialog:SetFrameStrata(oldstrata)
                end
        end
        t.OnCancel = function()
                if dialog and oldstrata then
                        dialog:SetFrameStrata(oldstrata)
                end
                local self = widget:GetUserData("self")
                local TriggerGlobalUpdate = widget:GetUserData("TriggerGlobalUpdate")
                if TriggerGlobalUpdate then
                        if self.valuesChangedCallback then 
                                for i, func in pairs(self.valuesChangedCallback) do
                                        func(self)
                                end
                        end
                end
        end
        for i = 1, select('#', ...) do
                t[i] = select(i, ...) or false
        end
        t.timeout = 0
        t.whileDead = 1
        t.hideOnEscape = 1

        dialog = StaticPopup_Show("AEGUIFACTORY_CONFIRM_DIALOG")
        if dialog then
                oldstrata = dialog:GetFrameStrata()
                dialog:SetFrameStrata("TOOLTIP")
        end
end


local function SetGUIOption(widget, event, ...)
        local self = widget:GetUserData("self")
        local db = widget:GetUserData("db")
        local key = widget:GetUserData("key")
        local UpdateOnMouseUp = widget:GetUserData("UpdateOnMouseUP")
        local TriggerGlobalUpdate = widget:GetUserData("TriggerGlobalUpdate")
        local func = widget:GetUserData("extraCallback")
        local confirm = widget:GetUserData("confirm")
        
        if confirm then ConfirmPupup(widget, event, ...) return end

        if db and key then      
                if select("#", ...) > 1 then
                        for i = 1, select("#", ...) do
                                db[key] = db[key] or {}
                                if type(db[key]) ~= "table" then
                                        db[key] = {}
                                end
                                db[key][i] = select(i, ...)
                        end
                else
                        if widget.min then
                                local value = ...
                                if value < widget.min then value = widget.min end
                                if value > widget.max then value = widget.max end
                                db[key] = value
                        else
                                db[key] = ...
                        end
                end
        elseif db then
                local item, value = ...
                db[item] = value
        end
        
        if key and widget.SetValue then
                if widget.min then
                        local value = ...
                        if value < widget.min then value = widget.min end
                        if value > widget.max then value = widget.max end
                        widget:SetValue(value)
                else
                        widget:SetValue(...)
                end
        end
        
        if widget.SetColor then
                widget:SetColor(...)
        end
        
        if func then func(widget, event, ...) end       
        if TriggerGlobalUpdate then
                if self.valuesChangedCallback and not UpdateOnMouseUp then 
                        for i, func in pairs(self.valuesChangedCallback) do
                                func(self)
                        end
                end
        end
        
        if key then AceGUI:ClearFocus() end
end

-- Internal
-- Get Label now supports a callback setting, incase you set to interactive so you can pass in an onClick handler to the label
local function GetLabel(lType, self, text, color, size, font, flags, interactive, relativeWidth, callback)
        if text then    assert(type(text) == "string" or type(text) == "number", ("%s-GuiFactory. %q must be a string or number"):format(self.name, "text")) end
        if color then   assert(type(color)      == "table" and color[1] and #color > 2 and 
                type(color[1]) == "number" and
                type(color[2]) == "number" and
                type(color[3]) == "number", ("%s-GuiFactory. %q must be a numeric indexed table with at least 3 values, each of numeric type"):format(self.name, "color")) end
        if size then    assert(type(size)       == "number", ("%s-GuiFactory. %q must be a number"):format(self.name, "size")) end
        if font then    assert(type(font)       == "string", ("%s-GuiFactory. %q must be a string"):format(self.name, "font")) end
        if flags then   assert(type(flags)      == "string", ("%s-GuiFactory. %q must be a string"):format(self.name, "flags")) end
        
        local s = self.s[lType]
        
        color = color or s.fontColor or self.s.fontColor
        local label
        if interactive then
                label = AceGUI:Create("InteractiveLabel")
                label:SetCallback("OnClick", SetGUIOption)
                label:SetUserData("extraCallback", callback)
        else
                label = AceGUI:Create("UIF-Label")
        end
        
        label:SetImage([[Interface\Icons\Achievement_Dungeon_Ulduar77_25man]], 0, 1, 0, 1)
        label:SetImageSize(0, 0)
        label:SetImage(nil)
        label:SetFont(font or s.font or self.s.font, size or s.fontSize or self.s.fontSize, flags or s.fontFlags or self.s.fontFlags)
        label:SetColor(unpack(color))
        label:SetText(text)
        label:SetRelativeWidth(relativeWidth or 1)
        return label
end

--------------------
-- Labels

--- Create a TitleX object (Title1, Title2, Title3)
-- @paramsig [self ,] text [, color] [, size] [, font] [, flags] [, interactive]
-- @pram self Table that is the factory itself (optional when called with :Title1(..)
-- @param text Text to put in the label
-- @param color Table with 4 values 0.0-1.0 representing the RGB-value of the color
-- @param size Size of the font to use
-- @param font The fontfile to use
-- @param flags Font flags (THICKOUTLINE, OUTLINE, MONOCROME, NONE)
-- @interactive Boolean to tell if it should be an interactive text, meaning it triggers OnEnter and so on.
local function Title1(...)
        return GetLabel("Title1", ...)
end
local function Title2(...)
        return GetLabel("Title2", ...)
end
local function Title3(...)
        return GetLabel("Title3", ...)
end
AddEmbed("Title1", Title1)
AddEmbed("Title2", Title2)
AddEmbed("Title3", Title3)
AddEmbed("Title", Title1)
AddEmbed("MainTitleLabel", Title1)

local function Text1(...)
        return GetLabel("Text1", ...)
end
local function Text2(...)
        return GetLabel("Text2", ...)
end
local function Text3(...)
        return GetLabel("Text3", ...)
end
AddEmbed("Text1", Text1)
AddEmbed("Text2", Text2)
AddEmbed("Text3", Text3)
AddEmbed("NormalText", Text1)

--- Create a ListLevel1 object (ListLevel1, ListLevel2, ListLevel3)
-- @paramsig [self ,] text [, color] [, size] [, font] [, flags] [, interactive]
-- @pram self Table that is the factory itself (optional when called with :Title1(..)
-- @param text Text to put in the label
-- @param color Table with 4 values 0.0-1.0 representing the RGB-value of the color
-- @param size Size of the font to use
-- @param font The fontfile to use
-- @param flags Font flags (THICKOUTLINE, OUTLINE, MONOCROME, NONE)
-- @interactive Boolean to tell if it should be an interactive text, meaning it triggers OnEnter and so on.
local function ListLevel1(self, text, color, size, font, flags, interactive)
        return GetLabel("ListLevel1", self, text, color, size, font, flags, interactive)
end
local function ListLevel1(self, text, color, size, font, flags, interactive)
        return GetLabel("ListLevel2", self, text, color, size, font, flags, interactive)
end
local function ListLevel1(self, text, color, size, font, flags, interactive)
        return GetLabel("ListLevel3", self, text, color, size, font, flags, interactive)
end
AddEmbed("ListLevel1", ListLevel1)
AddEmbed("ListLevel3", ListLevel2)
AddEmbed("ListLevel2", ListLevel3)
AddEmbed("ListText", ListLevel1)

---------------------
-- Frame

-- Create a main window for your GUI
-- @paramsig [self, ] text
-- @param self Table that is the factory itself, should not be passed when used lik Factory:Frame(...)
-- @param text Text to put in the title area of the window
local function Frame(self, text)
        local s = self.s["Frame"]
        
        local group = AceGUI:Create("UIF-Frame")
        group:SetTitleFont(s.font or self.s.font, s.fontSize or self.s.fontSize, s.fontFlags or self.s.fontFlags)
        group:SetTitleFontColor(s.fontColor or self.s.fontColor)
        group:SetBorderColor(s.borderColor or self.s.borderColor)
        group:SetBackColor(s.bgColor or self.s.bgColor)
        group:SetTitle(text)
        
        local button = self:Button("")
        
        group:SetButton(button)
        
        return group
end
AddEmbed("Frame", Frame)

---------------------
-- Dropdown group

local function DropdownGroup(self, text)
        local s = self.s["DropdownGroup"]
        
        local group = AceGUI:Create("UIF-DropdownGroup")
        group:SetFullWidth(true)
        group:SetFont(s.font or self.s.font, s.fontSize or self.s.fontSize, s.fontFlags or self.s.fontFlags)
        group:SetFontColor(s.fontColor or self.s.fontColor)
        group:SetBorderColor(s.borderColor or self.s.borderColor)
        
        group:SetTitle(text)
        
        local drop = InternalDrop(self)
        group:SetDropdownWidget(drop)
        return group
end
AddEmbed("DropdownGroup", DropdownGroup)

----------------------
-- Tree group

local function TreeGroup(self)
        local s = self.s["TreeGroup"]
        
        local group = AceGUI:Create("UIF-TreeGroup")
        group:SetFullWidth(true)
        group:SetFont(s.font or self.s.font, s.fontSize or self.s.fontSize, s.fontFlags or self.s.fontFlags)
        group:SetFontColor(s.fontColor or self.s.fontColor)
        group:SetSubFont(s.subFont or self.s.font, s.subFontSize or self.s.fontSize, s.subFontFlags or self.s.fontFlags)
        group:SetSubColor(s.subColor or self.s.fontColor)
        group:SetBorderColor(s.borderColor or self.s.borderColor)
        return group
end
AddEmbed("TreeGroup", TreeGroup)

----------------------
-- Tab group

local function TGroup(tType, self, text)
        if text then    assert(type(text)       == "string", ("%s-GuiFactory. %q must be a string"):format(self.name, "text")) end
        
        local s = self.s[tType]
        
        local group = AceGUI:Create("UIF-TabGroup")     
        
        group:SetBorderColor(s.borderColor or self.s.borderColor)
        group:SetBackColor(s.bgColor)
        group:SetFont(s.font or self.s.font, s.fontSize or self.s.fontSize, s.fontFlags or self.s.fontFlags)
        group:SetFontColor(s.fontColor or self.s.fontColor)
        
        group:SetTitle(text)
        
        group:SetFullWidth(true)
        group:SetLayout("Flow")

        return group
end

local function TabGroup1(self, text)
        return TGroup("TabGroup1", self, text)
end
local function TabGroup2(self, text)
        return TGroup("TabGroup2", self, text)
end
local function TabGroup2(self, text)
        return TGroup("TabGroup3", self, text)
end
AddEmbed("TabGroup1", TabGroup1)
AddEmbed("TabGroup", TabGroup1) -- Backwards compability
AddEmbed("TabGroup2", TabGroup2)
AddEmbed("TabGroup3", TabGroup3)

----------------------
-- Inline group

local function IGroup(gType, self, text, bgColor, borderColor)
        if text then    assert(type(text)       == "string", ("%s-GuiFactory. %q must be a string"):format(self.name, "text")) end
        if bgColor then         assert(type(bgColor)    == "table" and #bgColor > 2 and 
                type(bgColor[1]) == "number" and
                type(bgColor[2]) == "number" and
                type(bgColor[3]) == "number", ("%s-GuiFactory. %q must be a numeric indexed table with at least 3 values, each of numeric type"):format(self.name, "bgColor")) end
        if borderColor then     assert(type(borderColor)        == "table" and #borderColor > 2 and 
                type(borderColor[1]) == "number" and
                type(borderColor[2]) == "number" and
                type(borderColor[3]) == "number", ("%s-GuiFactory. %q must be a numeric indexed table with at least 3 values, each of numeric type"):format(self.name, "borderColor")) end
        
        local s = self.s[gType]
        
        local group = AceGUI:Create("UIF-InlineGroup")
        group:SetLayout("Flow")
        group:SetFullWidth(true)
        group:SetTitle(text)
        group:SetFont(s.font or self.s.font, s.fontSize or self.s.fontSize, s.fontFlags or self.s.fontFlags)
        group:SetFontColor(s.fontColor or self.s.fontColor)
        group:SetBGColor(bgColor or s.bgColor or self.s.bgColor)
        group:SetBorderColor(borderColor or s.borderColor or self.s.borderColor)
        
        return group
end

local function InlineGroup1(self, text, bgColor, borderColor)
        return IGroup("InlineGroup1", self, text, bgColor, borderColor)
end
local function InlineGroup2(self, text, bgColor, borderColor)
        return IGroup("InlineGroup2", self, text, bgColor, borderColor)
end
local function InlineGroup3(self, text, bgColor, borderColor)
        return IGroup("InlineGroup3", self, text, bgColor, borderColor)
end
AddEmbed("InlineGroup1", InlineGroup1)
AddEmbed("InlineGroup2", InlineGroup2)
AddEmbed("InlineGroup3", InlineGroup3)
AddEmbed("InlineGroup", InlineGroup1)

-- Mewline
local function NewLine(self, height)
        local t = AceGUI:Create("UIF-NewLine")
        t:SetHeight(height or 2)
        t:SetFullWidth(true)
        return t
end
AddEmbed("NewLine", NewLine)

local function Spacer(self, width)
        local t = AceGUI:Create("UIF-NewLine")
        t:SetWidth(width or 2)
        t:SetFullWidth(false)
        t:SetHeight(10)         
        return t
end
AddEmbed("Spacer", Spacer)

-- Changing Widgets

local function Slider(self, text, db, key, min, max, step, callback, relativeWidth)
        assert(text and type(text) == "string", ("%s-GuiFactory. %q must be a string"):format(self.name, "text"))
        assert(db and type(db) == "table", ("%s-GuiFactory. %q must be a table"):format(self.name, "db"))
        assert(key, ("%s-GuiFactory. %q must be supplied"):format(self.name, "key"))
        assert(db[key], ("%s-GuiFactory. %q does not contain %q"):format(self.name, "db", key))
        if callback then assert(type(callback) == "function", ("%s-GuiFactory. %q must be a function"):format(self.name, "callback")) end
        if min then assert(type(min) == "number", ("%s-GuiFactory. %q must be a number"):format(self.name, "min")) end
        if max then assert(type(max) == "number", ("%s-GuiFactory. %q must be a number"):format(self.name, "max")) end
        if step then assert(type(step) == "number", ("%s-GuiFactory. %q must be a number"):format(self.name, "step")) end
        if relativeWidth then assert(type(relativeWidth) == "number", ("%s-GuiFactory. %q must be a number"):format(self.name, "relativeWidth")) end
        
        local s = self.s["Slider"]      
        
        local slider = AceGUI:Create("UIF-Slider")
        slider:SetLabel(text)
        slider:SetFont(s.font or self.s.font, s.fontSize or self.s.fontSize, s.fontFlags or self.s.fontFlags)
        slider:SetFontColor(s.fontColor or self.s.fontColor)
        slider:SetSliderValues(min or 0, max or 100, step or 1)
        slider:SetValue(db[key])        
        slider:SetUserData("db", db)
        slider:SetUserData("key", key)
        slider:SetUserData("extraCallback", callback)
        slider:SetUserData("self", self)
        slider:SetUserData("UpdateOnMouseUP", true)
        slider:SetCallback("OnValueChanged", SetGUIOption)
        slider:SetCallback("OnMouseUp", UpdateTrigger)
        
        if relativeWidth then slider:SetRelativeWidth(relativeWidth) end
        
        return slider
end
AddEmbed("Slider", Slider)

local function PositionSlider(self, type, text, db, key, step, callback, relativeWidth)
        local min, max
        if string.lower(type) == "x" then
                min = -floor(GetScreenWidth() * UIParent:GetEffectiveScale())
                max = floor(GetScreenWidth() * UIParent:GetEffectiveScale())
        else
                min = -floor(GetScreenHeight() * UIParent:GetEffectiveScale()) 
                max = floor(GetScreenHeight() * UIParent:GetEffectiveScale())
        end
        
        return Slider(self, text, db, key, min, max, step, callback, relativeWidth)
end
AddEmbed("PositionSlider", PositionSlider)

local function CheckBox(self, text, db, key, callback, description, relativeWidth, globalUpdate)
        assert(text and type(text) == "string", ("%s-GuiFactory. %q must be a string"):format(self.name, "text"))
        assert(db and type(db) == "table", ("%s-GuiFactory. %q must be a table"):format(self.name, "db"))
        assert(key, ("%s-GuiFactory. %q must be supplied"):format(self.name, "key"))
        if callback then assert(type(callback) == "function", ("%s-GuiFactory. %q must be a function"):format(self.name, "callback")) end
        if relativeWidth then assert(type(relativeWidth) == "number", ("%s-GuiFactory. %q must be a number"):format(self.name, "relativeWidth")) end
        
        local s = self.s["CheckBox"]
        
        local check = AceGUI:Create("UIF-CheckBox")
        check:SetFullWidth(true)
        check:SetLabel(text)
        check:SetValue(db[key])
        check:SetFont(s.font or  self.s.font, s.fontSize or self.s.fontSize, s.fontFlags or self.s.fontFlags)
        check:SetFontColor(s.fontColor or self.s.fontColor)
        if description then
                check:SetDescription(description)
        end
        
        check:SetUserData("db", db)
        check:SetUserData("key", key)
        check:SetUserData("extraCallback", callback)
        check:SetUserData("self", self)
        check:SetUserData("TriggerGlobalUpdate", globalUpdate)
        check:SetCallback("OnValueChanged", SetGUIOption)       
        
        if relativeWidth then check:SetRelativeWidth(relativeWidth) end
        
        return check
end
AddEmbed("CheckBox", CheckBox)

local function ColorSelect(self, text, db, key, callback, hasAlpha, relativeWidth)
        assert(text and type(text) == "string", ("%s-GuiFactory. %q must be a string"):format(self.name, "text"))
        assert(db and type(db) == "table", ("%s-GuiFactory. %q must be a table"):format(self.name, "db"))
        assert(key, ("%s-GuiFactory. %q must be supplied"):format(self.name, "key"))
        if callback then assert(type(callback) == "function", ("%s-GuiFactory. %q must be a function"):format(self.name, "callback")) end
        if hasAlpha then assert(hasAlpha and type(hasAlpha) == "boolean", ("%s-GuiFactory. %q must be a boolean"):format(self.name, "hasAlpha")) end
        if relativeWidth then assert(type(relativeWidth) == "number", ("%s-GuiFactory. %q must be a number"):format(self.name, "relativeWidth")) end
        
        local s = self.s["CheckBox"]
        
        local color = AceGUI:Create("UIF-ColorPicker")
        color:SetLabel(text)
        color:SetFont(s.font or self.s.font, s.fontSize or self.s.fontSize, s.fontFlags or self.s.fontFlags)
        color:SetFontColor(s.fontColor or self.s.fontColor)
        if db[key] and type(db[key]) == "table" then
                color:SetColor(unpack(db[key]))
        end
        color:SetHasAlpha(hasAlpha)
        
        color:SetUserData("db", db)
        color:SetUserData("key", key)
        color:SetUserData("extraCallback", callback)
        color:SetUserData("self", self)
        color:SetCallback("OnValueChanged", SetGUIOption)
        color:SetUserData("UpdateOnMouseUP", true)
        color:SetCallback("OnValueConfirmed", UpdateTrigger)    
        
        if relativeWidth then color:SetRelativeWidth(relativeWidth) end
        
        return color
end
AddEmbed("ColorSelect", ColorSelect)

-----------------------
-- Other

InternalButton = function(self)
        local s = self.s["Button"]
        
        local color = color or s.fontColor or self.s.fontColor
        
        local button = AceGUI:Create("UIF-Button")
        button:SetText(text)
        button:SetFont(font or s.font or self.s.font, size or s.fontSize or self.s.fontSize, flags or s.fontFlags or self.s.fontFlags)
        button:SetFontColor(color)
        
        return button
end

local function Button(self, text, callback, font, size, flags, color, relativeWidth)
        assert(text and type(text) == "string", ("%s-GuiFactory. %q must be a string"):format(self.name, "text"))
        if color then   assert(type(color)      == "table" and color[1] and #color > 2 and 
                type(color[1]) == "number" and
                type(color[2]) == "number" and
                type(color[3]) == "number", ("%s-GuiFactory. %q must be a numeric indexed table with at least 3 values, each of numeric type"):format(self.name, "color")) end
        if size then    assert(type(size)       == "number", ("%s-GuiFactory. %q must be a number"):format(self.name, "size")) end
        if font then    assert(type(font)       == "string", ("%s-GuiFactory. %q must be a string"):format(self.name, "font")) end
        if flags then   assert(type(flags)      == "string", ("%s-GuiFactory. %q must be a string"):format(self.name, "flags")) end
        
        local s = self.s["Button"]
        
        color = color or s.fontColor or self.s.fontColor
        
        local button = AceGUI:Create("UIF-Button")
        button:SetText(text)
        button:SetFont(font or s.font or self.s.font, size or s.fontSize or self.s.fontSize, flags or s.fontFlags or self.s.fontFlags)
        button:SetFontColor(color)
        
        button:SetUserData("self", self)
        button:SetUserData("extraCallback", callback)
        button:SetCallback("OnClick", SetGUIOption)     
        button:SetUserData("UpdateOnMouseUP", true)
        button:SetCallback("OnMouseUp", UpdateTrigger)
                
        if not relativeWidth then
                button:SetWidth(button.text:GetStringWidth() + 30)
        else
                button:SetRelativeWidth(relativeWidth)
        end
        
        return button
end
AddEmbed("Button", Button)

----------------------
-- Dropdown

InternalDrop = function(self, text, callback, list, relativeWidth)
        local s = self.s["Dropdown"]

        local drop = AceGUI:Create("UIF-Dropdown")
        drop:SetItemFont(s.itemFont or self.s.font, s.itemFontSize or self.s.fontSize, s.itemFontFlags or self.s.fontFlags)
        drop:SetItemFontColor(s.itemFontColor or self.s.fontColor)
        drop:SetFont(s.font or self.s.font, s.fontSize or self.s.fontSize, s.fontFlags or self.s.fontFlags)
        drop:SetFontColor(s.fontColor or self.s.fontColor)
        
        drop:SetUserData("self", self)
        drop:SetLabel(text)
        drop:SetList(list)
        drop:SetUserData("extraCallback", callback)
        drop:SetCallback("OnValueChanged", SetGUIOption)
        if relativeWidth then drop:SetRelativeWidth(relativeWidth) end
        
        return drop
end
AddEmbed("SimpleDropdown", InternalDrop)

local function Dropdown(self, text, db, key, callback, list, relativeWidth, globalUpdate)
        assert(text and type(text) == "string", ("%s-GuiFactory. %q must be a string"):format(self.name, "text"))
        assert(db and type(db) == "table", ("%s-GuiFactory. %q must be a table"):format(self.name, "db"))
        assert(key, ("%s-GuiFactory. %q must be supplied"):format(self.name, "key"))
        if callback then assert(type(callback) == "function", ("%s-GuiFactory. %q must be a function"):format(self.name, "callback")) end
        if relativeWidth then assert(type(relativeWidth) == "number", ("%s-GuiFactory. %q must be a number"):format(self.name, "relativeWidth")) end

        local drop = InternalDrop(self)
        drop:SetLabel(text)
        
        drop:SetUserData("db", db)
        drop:SetUserData("key", key)
        drop:SetUserData("self", self)
        drop:SetList(list)      
        drop:SetUserData("extraCallback", callback)
        drop:SetCallback("OnValueChanged", SetGUIOption)
        drop:SetValue(db[key])
        
        drop:SetUserData("TriggerGlobalUpdate", globalUpdate)
        
        if relativeWidth then drop:SetRelativeWidth(relativeWidth) end
        
        return drop
end
AddEmbed("Dropdown", Dropdown)

local function MultiSelectDropdown(self, text, db, callback, list, relativeWidth)
        assert(text and type(text) == "string", ("%s-GuiFactory. %q must be a string"):format(self.name, "text"))
        assert(db and type(db) == "table", ("%s-GuiFactory. %q must be a table"):format(self.name, "db"))
        if callback then assert(type(callback) == "function", ("%s-GuiFactory. %q must be a function"):format(self.name, "callback")) end
        if relativeWidth then assert(type(relativeWidth) == "number", ("%s-GuiFactory. %q must be a number"):format(self.name, "relativeWidth")) end
        
        local drop = InternalDrop(self)
        drop:SetLabel(text)
        drop:SetMultiselect(true)
        
        drop:SetUserData("db", db)
        drop:SetUserData("self", self)
        if list then
                drop:SetList(list)
                for i in pairs(list) do
                        if db[i] then drop:SetItemValue(i, true) end
                end
        end
        drop:SetUserData("extraCallback", callback)
        drop:SetCallback("OnValueChanged", SetGUIOption)
        
        if relativeWidth then drop:SetRelativeWidth(relativeWidth) end
        
        return drop
end
AddEmbed("MultiSelectDropdown", MultiSelectDropdown)

local function LSMDropdown(self, dtype, text, db, key, callback, relativeWidth)
        assert(text and type(text) == "string", ("%s-GuiFactory. %q must be a string"):format(self.name, "text"))
        assert(db and type(db) == "table", ("%s-GuiFactory. %q must be a table"):format(self.name, "db"))
        assert(key, ("%s-GuiFactory. %q must be supplied"):format(self.name, "key"))
        if callback then assert(type(callback) == "function", ("%s-GuiFactory. %q must be a function"):format(self.name, "callback")) end
        if relativeWidth then assert(type(relativeWidth) == "number", ("%s-GuiFactory. %q must be a number"):format(self.name, "relativeWidth")) end

        local drop
        local dtype = string.lower(dtype)
        if dtype == "statusbar" then
                drop = AceGUI:Create("LSM30_Statusbar")
                drop:SetList(LSM:HashTable("statusbar"))
        elseif dtype == "font" then
                drop = AceGUI:Create("LSM30_Font")
                drop:SetList(LSM:HashTable("font"))
        elseif dtype == "background" then
                drop = AceGUI:Create("LSM30_Background")
                drop:SetList(LSM:HashTable("background"))
        elseif dtype == "border" then
                drop = AceGUI:Create("LSM30_Border")
                drop:SetList(LSM:HashTable("border"))
        elseif dtype == "sound" then
                drop = AceGUI:Create("LSM30_Sound")
                drop:SetList(LSM:HashTable("sound"))
        else
                assert(drop ~= nil, ("%s-GuiFactory. %q is not a valid LSM dropdown."):format(self.name, "dtype"))
        end
        
        
        drop:SetLabel(text)     
        drop:SetValue(db[key])
        
        drop:SetUserData("db", db)
        drop:SetUserData("key", key)
        drop:SetUserData("extraCallback", callback)
        drop:SetUserData("self", self)
        drop:SetCallback("OnValueChanged", SetGUIOption)
        
        if relativeWidth then drop:SetRelativeWidth(relativeWidth) end
        
        return drop
end
AddEmbed("LSMDropdown", LSMDropdown)

-- Profile
local AceProfileOption
do      
        local function GetAllPorfiles(db)
                local profiles = {      
                        ["Default"] = "Default",
                        [db.keys.char] = db.keys.char,
                        [db.keys.realm] = db.keys.realm,
                        [db.keys.class] = UnitClass("player")
                }
                local ExistingProfiles =   {}
                local count = 0
                
                for i, profileName in pairs(db:GetProfiles()) do
                        profiles[profileName] = profileName
                        count = count + 1
                end
                
                return profiles, count
        end

        local function GetExistingProfiles(db, nocurrent)
                local profiles = {}
                local currentProfile = db:GetCurrentProfile()
                local count = 0
                
                for i, profileName in pairs(db:GetProfiles()) do
                        if not (nocurrent and profileName == currentProfile) then
                                profiles[profileName] = profileName
                                count = count + 1
                        end
                end
                
                return profiles, count
        end

        local function RefreshProfileLists(widget)
                local SelectProfile = widget:GetUserData("SelectProfile")
                if not SelectProfile then return end
                local CopyProfile = widget:GetUserData("CopyProfile")
                local DeleteProfile = widget:GetUserData("DeleteProfile")
                local db = SelectProfile:GetUserData("Database")
                
                local profiles, count = GetAllPorfiles(db)
                SelectProfile:SetList(profiles)
                SelectProfile:SetValue(db:GetCurrentProfile())
                profiles, count = GetExistingProfiles(db, true)
                CopyProfile:SetList(profiles)
                CopyProfile:SetDisabled(count == 0)
                CopyProfile:SetValue()
                DeleteProfile:SetList(profiles)
                DeleteProfile:SetDisabled(count == 0)
                DeleteProfile:SetValue()
        end

        -- Create a group containing options to handle AceDB-3.0 profiles.
        -- @paramsig [self ,] db
        -- @param self Table that is the factory itself, Not required when used via Factory:AceProfileOption(...)
        -- @param db AceDB-3.0 database object to create the profile options for.
        AceProfileOption = function(self, db)
                assert(db and db.ResetDB, ("%s-GuiFactory. %q must proper AceDB object."):format(self.name, "db"))
                
                local group = self:InlineGroup("Profile Settings")
                local profiles, count, text
                
                local SelectProfile = InternalDrop(self)
                SelectProfile:SetLabel("Profiles")
                SelectProfile:SetUserData("Database", db)
                SelectProfile:SetCallback("OnValueChanged", function(widget, event, value)
                        widget:GetUserData("Database"):SetProfile(value)
                        RefreshProfileLists(group)
                end)
                group:AddChild(SelectProfile)
                
                local ResetProfile = InternalButton(self)
                ResetProfile:SetText("Reset")
                ResetProfile:SetWidth(ResetProfile.text:GetStringWidth() + 30)
                ResetProfile:SetUserData("Database", db)
                ResetProfile:SetUserData("self", self)
                ResetProfile:SetUserData("extraCallback", function(widget, event)
                        widget:GetUserData("Database"):ResetProfile()
                end)
                ResetProfile:SetCallback("OnClick", SetGUIOption)       
                ResetProfile:SetUserData("confirm", true)
                group:AddChild(ResetProfile)
                
                group:AddChild(self:NewLine(15))
                group:AddChild(self:NormalText("Copy a profile and replace the current profiles settings."))
                local CopyProfile = InternalDrop(self)
                CopyProfile:SetLabel("Copy Profile")
                CopyProfile:SetUserData("Database", db)
                CopyProfile:SetCallback("OnValueChanged", function(widget, event, value)
                        local db = widget:GetUserData("Database")
                        db:CopyProfile(value)
                        RefreshProfileLists(group)
                end)
                group:AddChild(CopyProfile)
                
                group:AddChild(self:NewLine(15))
                group:AddChild(self:NormalText("Delete one of the existing profiles"))
                local DeleteProfile = InternalDrop(self)
                DeleteProfile:SetLabel("Delete Profile")
                DeleteProfile:SetUserData("Database", db)
                DeleteProfile:SetUserData("self", self)
                DeleteProfile:SetUserData("extraCallback", function(widget, event, value)                       
                        local db = widget:GetUserData("Database")
                        if value then
                                db:DeleteProfile(value)
                        end
                        RefreshProfileLists(group)
                end)
                DeleteProfile:SetCallback("OnValueChanged", SetGUIOption)       
                DeleteProfile:SetUserData("confirm", true)
                group:AddChild(DeleteProfile)           
                
                group:AddChild(self:NewLine(15))
                group:AddChild(self:NormalText("Create a new profile, it will then become the active profile."))
                local CreateProfile = AceGUI:Create("EditBox")
                CreateProfile:SetLabel("Create Profile")
                CreateProfile:SetUserData("Database", db)
                CreateProfile:SetCallback("OnEnterPressed", function(widget, event, value)
                        local db = widget:GetUserData("Database")
                        db:SetProfile(value)
                        widget.editbox:ClearFocus()
                        widget:SetText()
                        RefreshProfileLists(group)
                end)
                group:AddChild(CreateProfile)
                
                group:SetUserData("SelectProfile", SelectProfile)
                group:SetUserData("CopyProfile", CopyProfile)
                group:SetUserData("DeleteProfile", DeleteProfile)
                
                RefreshProfileLists(group)
                
                return group            
        end
end
AddEmbed("AceProfileOption", AceProfileOption)

local function SetValuesChangedCallback(self, func)
        assert(type(func) == "function", "The callback must be a function")
        self.valuesChangedCallback = self.valuesChangedCallback or {} 
        tinsert(self.valuesChangedCallback, func)
end
AddEmbed("SetValuesChangedCallback", SetValuesChangedCallback)

for fName, factory in pairs(UIF.factories) do
        Embed(factory)
end

-- Defaults
local defaultFont, defualtFondSize, defaultFontFlags = GameFontNormal:GetFont()

UIF.defaults = {
        font = defaultFont,
        fontSize = defualtFondSize,
        fontColor = {177/255, 219/255, 255/255},
        fontFlags = defaultFontFlags,
        borderColor = {0.2,0.3,0.37,1},
        bgColor = {0.11,0.16,0.19,1},
        
        MainTitle = {
                fontSize = 30,
                fontColor = {0.4, 0.6, 0.8},
                fontFlags = "OUTLINE"
        },
        
        -- Titles
        Title1 = {
                fontSize = 30,
                fontColor = {255/255, 248/255, 53/255},
                fontFlags = "OUTLINE"
        },
        Title2 = {
                fontSize = 20,
                fontColor = {18/255, 157/255, 143/255},
                fontFlags = "OUTLINE"
        },
        Title3 = {
                fontSize = 18,
                fontColor = {18/255, 157/255, 143/255},
                fontFlags = "OUTLINE"
        },
        
        -- Mornal texts
        Text1 = {
                fontSize = 16,
                fontColor = {177/255, 219/255, 255/255},
        },
        Text2 = {
        },
        Text3 = {
        },
        
        -- Lists
        ListLevel1 = {
                fontSize = 16,
                fontColor = {0.96, 0.93, 0.49},
        },
        ListLevel2 = {
        },
        ListLevel3 = {
        },

        -- Frame
        Frame = {
                fontSize = 25,
                bgColor = {0.11,0.16,0.19,0.8},
        },
        DropdownGroup = {
        },
        Dropdown = {
                itemFontSize = 18,
        },
        TreeGroup = {
                fontColor = {0.4, 0.6, 0.8},            
        },
        TabGroup1 = {   
                fontSize = 20,
                tabFontSize = 35,
                bgColor = {0.11,0.16,0.19,1},
                borderColor = {0.2,0.3,0.37,1},
        },
        TabGroup2 = {   
                fontSize = 20,
                fontFlags = "OUTLINE",
                bgColor = {40/255, 45/255, 70/255},
                borderColor = {81/255, 96/255, 106/255},
                fontColor = {207/255, 218/255, 85/255},
        },
        TabGroup3 = {   
                fontSize = 20,
                fontFlags = "OUTLINE",
                bgColor = {40/255, 45/255, 70/255},
                borderColor = {81/255, 96/255, 106/255},
                fontColor = {207/255, 218/255, 85/255},
        },
        InlineGroup1 = {
                fontFlags = "OUTLINE",
                fontSize = 22,
        },
        InlineGroup2 = {
                bgColor = {40/255, 45/255, 70/255},
                borderColor = {81/255, 96/255, 106/255},
                fontColor = {207/255, 218/255, 85/255},
                fontSize = 22,
        },
        InlineGroup3 = {
                bgColor = {40/255, 55/255, 75/255},
                borderColor = {81/255, 96/255, 106/255},
                fontColor = {207/255, 100/255, 85/255},
                fontSize = 20,
        },
        Button = {
        },
        Slider = {              
        },
        CheckBox = {
        },
}

Compare with Previous | Blame