Mercurial > wow > hansgar_and_franzok_assist
diff Libs/DF/panel.lua @ 58:0682d738499b v8.0.1.058
- 8.0.1 Update.
| author | Tercio |
|---|---|
| date | Fri, 20 Jul 2018 19:04:12 -0300 |
| parents | 7c0f819a85c6 |
| children |
line wrap: on
line diff
--- a/Libs/DF/panel.lua Sun Mar 11 10:50:42 2018 -0300 +++ b/Libs/DF/panel.lua Fri Jul 20 19:04:12 2018 -0300 @@ -29,6 +29,40 @@ local PanelMetaFunctions = _G [DF.GlobalWidgetControlNames ["panel"]] +--> mixin for options functions +DF.OptionsFunctions = { + SetOption = function (self, optionName, optionValue) + if (self.options) then + self.options [optionName] = optionValue + else + self.options = {} + self.options [optionName] = optionValue + end + end, + + GetOption = function (self, optionName) + return self.options and self.options [optionName] + end, + + GetAllOptions = function (self) + if (self.options) then + local optionsTable = {} + for key, _ in pairs (self.options) do + optionsTable [#optionsTable + 1] = key + end + return optionsTable + else + return {} + end + end, + + BuildOptionsTable = function (self, defaultOptions, userOptions) + self.options = self.options or {} + DF.table.deploy (self.options, userOptions or {}) + DF.table.deploy (self.options, defaultOptions or {}) + end +} + ------------------------------------------------------------------------------------------------------------ --> metatables @@ -1216,19 +1250,21 @@ DF.IconPickFrame = CreateFrame ("frame", "DetailsFrameworkIconPickFrame", UIParent) tinsert (UISpecialFrames, "DetailsFrameworkIconPickFrame") - DF.IconPickFrame:SetFrameStrata ("DIALOG") + DF.IconPickFrame:SetFrameStrata ("TOOLTIP") DF.IconPickFrame:SetPoint ("center", UIParent, "center") DF.IconPickFrame:SetWidth (350) - DF.IconPickFrame:SetHeight (227) + DF.IconPickFrame:SetHeight (277) DF.IconPickFrame:EnableMouse (true) DF.IconPickFrame:SetMovable (true) + DF:CreateTitleBar (DF.IconPickFrame, "Icon Picker") + DF.IconPickFrame:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true}) DF.IconPickFrame:SetBackdropBorderColor (0, 0, 0) DF.IconPickFrame:SetBackdropColor (24/255, 24/255, 24/255, .8) - DF.IconPickFrame:SetFrameLevel (1) + DF.IconPickFrame:SetFrameLevel (5000) DF.IconPickFrame:SetScript ("OnMouseDown", function (self) if (not self.isMoving) then @@ -1249,16 +1285,29 @@ DF.IconPickFrame.preview = CreateFrame ("frame", nil, UIParent) DF.IconPickFrame.preview:SetFrameStrata ("tooltip") + DF.IconPickFrame.preview:SetFrameLevel (6001) DF.IconPickFrame.preview:SetSize (76, 76) + + local preview_image_bg = DF:NewImage (DF.IconPickFrame.preview, nil, 76, 76) + preview_image_bg:SetDrawLayer ("background", 0) + preview_image_bg:SetAllPoints (DF.IconPickFrame.preview) + preview_image_bg:SetColorTexture (0, 0, 0) + local preview_image = DF:NewImage (DF.IconPickFrame.preview, nil, 76, 76) preview_image:SetAllPoints (DF.IconPickFrame.preview) + DF.IconPickFrame.preview.icon = preview_image DF.IconPickFrame.preview:Hide() + --serach DF.IconPickFrame.searchLabel = DF:NewLabel (DF.IconPickFrame, nil, "$parentSearchBoxLabel", nil, "search:", font, size, color) - DF.IconPickFrame.searchLabel:SetPoint ("topleft", DF.IconPickFrame, "topleft", 12, -20) + DF.IconPickFrame.searchLabel:SetPoint ("topleft", DF.IconPickFrame, "topleft", 12, -36) + DF.IconPickFrame.searchLabel:SetTemplate (DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE")) + DF.IconPickFrame.search = DF:NewTextEntry (DF.IconPickFrame, nil, "$parentSearchBox", nil, 140, 20) DF.IconPickFrame.search:SetPoint ("left", DF.IconPickFrame.searchLabel, "right", 2, 0) + DF.IconPickFrame.search:SetTemplate (DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE")) + DF.IconPickFrame.search:SetHook ("OnTextChanged", function() DF.IconPickFrame.searching = DF.IconPickFrame.search:GetText() if (DF.IconPickFrame.searching == "") then @@ -1273,12 +1322,48 @@ end end) + --manually enter the icon path + DF.IconPickFrame.customIcon = DF:CreateLabel (DF.IconPickFrame, "Icon Path:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE")) + DF.IconPickFrame.customIcon:SetPoint ("bottomleft", DF.IconPickFrame, "bottomleft", 12, 16) + + DF.IconPickFrame.customIconEntry = DF:CreateTextEntry (DF.IconPickFrame, function()end, 200, 20, "CustomIconEntry", _, _, DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE")) + DF.IconPickFrame.customIconEntry:SetPoint ("left", DF.IconPickFrame.customIcon, "right", 2, 0) + + DF.IconPickFrame.customIconEntry:SetHook ("OnTextChanged", function() + DF.IconPickFrame.preview:SetPoint ("bottom", DF.IconPickFrame.customIconEntry.widget, "top", 0, 2) + DF.IconPickFrame.preview.icon:SetTexture (DF.IconPickFrame.customIconEntry:GetText()) + DF.IconPickFrame.preview:Show() + end) + + DF.IconPickFrame.customIconEntry:SetHook ("OnEnter", function() + DF.IconPickFrame.preview:SetPoint ("bottom", DF.IconPickFrame.customIconEntry.widget, "top", 0, 2) + DF.IconPickFrame.preview.icon:SetTexture (DF.IconPickFrame.customIconEntry:GetText()) + DF.IconPickFrame.preview:Show() + end) + --> close button local close_button = CreateFrame ("button", nil, DF.IconPickFrame, "UIPanelCloseButton") close_button:SetWidth (32) close_button:SetHeight (32) close_button:SetPoint ("TOPRIGHT", DF.IconPickFrame, "TOPRIGHT", -8, -7) close_button:SetFrameLevel (close_button:GetFrameLevel()+2) + close_button:SetAlpha (0) --just hide, it is used below + + --> accept custom icon button + local accept_custom_icon = function() + local path = DF.IconPickFrame.customIconEntry:GetText() + + DF:QuickDispatch (DF.IconPickFrame.callback, path, DF.IconPickFrame.param1, DF.IconPickFrame.param2) + + if (DF.IconPickFrame.click_close) then + close_button:Click() + end + end + + DF.IconPickFrame.customIconAccept = DF:CreateButton (DF.IconPickFrame, accept_custom_icon, 82, 20, "Accept", nil, nil, nil, nil, nil, nil, DF:GetTemplate ("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE")) + DF.IconPickFrame.customIconAccept:SetPoint ("left", DF.IconPickFrame.customIconEntry, "right", 2, 0) + + --fill with icons local MACRO_ICON_FILENAMES = {} local SPELLNAMES_CACHE = {} @@ -1320,18 +1405,25 @@ GetLooseMacroIcons (MACRO_ICON_FILENAMES) GetMacroIcons (MACRO_ICON_FILENAMES) GetMacroItemIcons (MACRO_ICON_FILENAMES) - + + --reset the custom icon text entry + DF.IconPickFrame.customIconEntry:SetText ("") + --reset the search text entry + DF.IconPickFrame.search:SetText ("") end) DF.IconPickFrame:SetScript ("OnHide", function() wipe (MACRO_ICON_FILENAMES) + DF.IconPickFrame.preview:Hide() collectgarbage() end) DF.IconPickFrame.buttons = {} local OnClickFunction = function (self) - DF.IconPickFrame.callback (self.icon:GetTexture(), DF.IconPickFrame.param1, DF.IconPickFrame.param2) + + DF:QuickDispatch (DF.IconPickFrame.callback, self.icon:GetTexture(), DF.IconPickFrame.param1, DF.IconPickFrame.param2) + if (DF.IconPickFrame.click_close) then close_button:Click() end @@ -1362,7 +1454,7 @@ newcheck:SetScript ("OnClick", OnClickFunction) newcheck.param1 = i+1 - newcheck:SetPoint ("topleft", DF.IconPickFrame, "topleft", 12 + (i*30), -40) + newcheck:SetPoint ("topleft", DF.IconPickFrame, "topleft", 12 + (i*30), -60) newcheck:SetID (i+1) DF.IconPickFrame.buttons [#DF.IconPickFrame.buttons+1] = newcheck newcheck:SetScript ("OnEnter", onenter) @@ -1455,6 +1547,7 @@ end local scroll = CreateFrame ("ScrollFrame", "DetailsFrameworkIconPickFrameScroll", DF.IconPickFrame, "ListScrollFrameTemplate") + DF:ReskinSlider (scroll) local ChecksFrame_Update = function (self) @@ -1527,7 +1620,7 @@ DF.IconPickFrame.updateFunc = ChecksFrame_Update - scroll:SetPoint ("topleft", DF.IconPickFrame, "topleft", -18, -37) + scroll:SetPoint ("topleft", DF.IconPickFrame, "topleft", -18, -58) scroll:SetWidth (330) scroll:SetHeight (178) scroll:SetScript ("OnVerticalScroll", function (self, offset) FauxScrollFrame_OnVerticalScroll (scroll, offset, 20, ChecksFrame_Update) end) @@ -1609,9 +1702,12 @@ local SimplePanel_frame_backdrop_color = {0, 0, 0, 0.9} local SimplePanel_frame_backdrop_border_color = {0, 0, 0, 1} +--with_label was making the frame stay in place while its parent moves +--the slider was anchoring to with_label and here here were anchoring the slider again function DF:CreateScaleBar (frame, config) - local scaleBar = DF:CreateSlider (frame, 120, 14, 0.6, 1.6, 0.1, config.scale, true, "ScaleBar", nil, "Scale:", DF:GetTemplate ("slider", "OPTIONS_SLIDER_TEMPLATE"), DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE")) - scaleBar:SetPoint ("right", frame.Close, "left", -26, 0) + local scaleBar, text = DF:CreateSlider (frame, 120, 14, 0.6, 1.6, 0.1, config.scale, true, "ScaleBar", nil, "Scale:", DF:GetTemplate ("slider", "OPTIONS_SLIDER_TEMPLATE"), DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE")) + --scaleBar:SetPoint ("right", frame.Close, "left", -26, 0) + text:SetPoint ("topleft", frame, "topleft", 12, -7) scaleBar:SetFrameLevel (DF.FRAMELEVEL_OVERLAY) scaleBar.OnValueChanged = function (_, _, value) config.scale = value @@ -1622,6 +1718,10 @@ scaleBar:SetHook ("OnMouseUp", function() frame:SetScale (config.scale) end) + + scaleBar:SetAlpha (0.2) + + return scaleBar end local no_options = {} @@ -3531,15 +3631,20 @@ tabButton.mainFrame = mainFrame DF.TabContainerFunctions.CreateUnderlineGlow (tabButton) + local right_click_to_back if (i == 1) then - local right_click_to_back = DF:CreateLabel (f, "right click to close", 10, "gray") + right_click_to_back = DF:CreateLabel (f, "right click to close", 10, "gray") right_click_to_back:SetPoint ("bottomright", f, "bottomright", -1, 0) f.IsFrontPage = true else - local right_click_to_back = DF:CreateLabel (f, "right click to go back to main menu", 10, "gray") + right_click_to_back = DF:CreateLabel (f, "right click to go back to main menu", 10, "gray") right_click_to_back:SetPoint ("bottomright", f, "bottomright", -1, 0) end + if (options_table.hide_click_label) then + right_click_to_back:Hide() + end + f:SetScript ("OnMouseDown", DF.TabContainerFunctions.OnMouseDown) f:SetScript ("OnMouseUp", DF.TabContainerFunctions.OnMouseUp) @@ -3607,6 +3712,18 @@ widget:SetHook ("OnEnter", simple_list_box_onenter) widget:SetHook ("OnLeave", simple_list_box_onleave) widget.textcolor = self.options.textcolor + widget.textsize = self.options.text_size + widget.onleave_backdrop = self.options.backdrop_color + + widget.XButton = DF:CreateButton (widget, function()end, 16, 16) + widget.XButton:SetPoint ("topright", widget.widget, "topright") + widget.XButton:SetIcon ([[Interface\BUTTONS\UI-Panel-MinimizeButton-Up]], 16, 16, "overlay", nil, nil, 0, -4, 0, false) + widget.XButton.icon:SetDesaturated (true) + + if (not self.options.show_x_button) then + widget.XButton:Hide() + end + tinsert (self.widgets, widget) end self.nextWidget = self.nextWidget + 1 @@ -3620,16 +3737,29 @@ local widget = self:GetOrCreateWidget() widget:SetPoint ("topleft", self, "topleft", 1, -self.options.row_height * (self.nextWidget-2) - 4) widget:SetPoint ("topright", self, "topright", -1, -self.options.row_height * (self.nextWidget-2) - 4) + widget:SetClickFunction (self.func, value) + + if (self.options.show_x_button) then + widget.XButton:SetClickFunction (self.options.x_button_func, value) + widget.XButton.value = value + widget.XButton:Show() + else + widget.XButton:Hide() + end + widget.value = value if (self.options.icon) then if (type (self.options.icon) == "string" or type (self.options.icon) == "number") then - widget:SetIcon (self.options.icon, self.options.row_height, self.options.row_height) + local coords = type (self.options.iconcoords) == "table" and self.options.iconcoords or {0, 1, 0, 1} + widget:SetIcon (self.options.icon, self.options.row_height - 2, self.options.row_height - 2, "overlay", coords) + elseif (type (self.options.icon) == "function") then local icon = self.options.icon (value) if (icon) then - widget:SetIcon (icon, self.options.row_height, self.options.row_height) + local coords = type (self.options.iconcoords) == "table" and self.options.iconcoords or {0, 1, 0, 1} + widget:SetIcon (icon, self.options.row_height - 2, self.options.row_height - 2, "overlay", coords) end end else @@ -3652,6 +3782,10 @@ end widget.value = value + + local r, g, b, a = DF:ParseColors (self.options.backdrop_color) + widget:SetBackdropColor (r, g, b, a) + widget:Show() amt = amt + 1 end @@ -3669,7 +3803,12 @@ width = 230, icon = false, text = "", + text_size = 10, textcolor = "wheat", + + backdrop_color = {1, 1, 1, .5}, + panel_border_color = {0, 0, 0, 0.5}, + onenter = function (self, capsule) if (capsule) then capsule.textcolor = "white" @@ -3697,16 +3836,27 @@ f.nextWidget = 1 f.list_table = list_table f.func = function (self, button, value) - onclick (value) + --onclick (value) + DF:QuickDispatch (onclick, value) f:Refresh() end f.widgets = {} - f:SetBackdrop (backdrop) - f:SetBackdropColor (0, 0, 0, 0.3) - f:SetBackdropBorderColor (0, 0, 0, 0.5) + + DF:ApplyStandardBackdrop (f) + f.options = options or {} self.table.deploy (f.options, default_options) + if (f.options.x_button_func) then + local original_X_function = f.options.x_button_func + f.options.x_button_func = function (self, button, value) + DF:QuickDispatch (original_X_function, value) + f:Refresh() + end + end + + f:SetBackdropBorderColor (unpack (f.options.panel_border_color)) + f:SetSize (f.options.width + 2, f.options.height) local name = DF:CreateLabel (f, title, 12, "silver") @@ -3899,6 +4049,8 @@ function DF:CreateScrollBox (parent, name, refresh_func, data, width, height, line_amount, line_height, create_line_func, auto_amount, no_scroll) local scroll = CreateFrame ("scrollframe", name, parent, "FauxScrollFrameTemplate") + DF:ApplyStandardBackdrop (scroll) + scroll:SetSize (width, height) scroll.LineAmount = line_amount scroll.LineHeight = line_height @@ -3950,3 +4102,833 @@ return leftResizer, rightResizer end end + + +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- ~keybind + + +-------------------------------- +--> keybind frame ~key + + +local ignoredKeys = { + ["LSHIFT"] = true, + ["RSHIFT"] = true, + ["LCTRL"] = true, + ["RCTRL"] = true, + ["LALT"] = true, + ["RALT"] = true, + ["UNKNOWN"] = true, +} + +local mouseKeys = { + ["LeftButton"] = "type1", + ["RightButton"] = "type2", + ["MiddleButton"] = "type3", + ["Button4"] = "type4", + ["Button5"] = "type5", + ["Button6"] = "type6", + ["Button7"] = "type7", + ["Button8"] = "type8", + ["Button9"] = "type9", + ["Button10"] = "type10", + ["Button11"] = "type11", + ["Button12"] = "type12", + ["Button13"] = "type13", + ["Button14"] = "type14", + ["Button15"] = "type15", + ["Button16"] = "type16", +} + +local keysToMouse = { + ["type1"] = "LeftButton", + ["type2"] = "RightButton", + ["type3"] = "MiddleButton", + ["type4"] = "Button4", + ["type5"] = "Button5", + ["type6"] = "Button6", + ["type7"] = "Button7", + ["type8"] = "Button8", + ["type9"] = "Button9", + ["type10"] = "Button10", + ["type11"] = "Button11", + ["type12"] = "Button12", + ["type13"] = "Button13", + ["type14"] = "Button14", + ["type15"] = "Button15", + ["type16"] = "Button16", +} + +local keybind_set_data = function (self, new_data_table) + self.Data = new_data_table + self.keybindScroll:UpdateScroll() +end + +function DF:CreateKeybindBox (parent, name, data, callback, width, height, line_amount, line_height) + + local options_text_template = DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE") + local options_dropdown_template = DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE") + local options_switch_template = DF:GetTemplate ("switch", "OPTIONS_CHECKBOX_TEMPLATE") + local options_slider_template = DF:GetTemplate ("slider", "OPTIONS_SLIDER_TEMPLATE") + local options_button_template = DF:GetTemplate ("button", "OPTIONS_BUTTON_TEMPLATE") + + local SCROLL_ROLL_AMOUNT = line_amount + + --keybind set frame + local new_keybind_frame = CreateFrame ("frame", name, parent) + new_keybind_frame:SetSize (width, height) + + -- keybind scrollframe + local keybindScroll = CreateFrame ("scrollframe", "$parentScrollFrame", new_keybind_frame, "FauxScrollFrameTemplate") + keybindScroll:SetSize (1019, 348) + keybindScroll.Frames = {} + new_keybind_frame.keybindScroll = keybindScroll + + --waiting the player to press a key + new_keybind_frame.IsListening = false + + --check for valid data table + if (type (data) ~= "table") then + print ("error: data must be a table. DF > CreateKeybindBox()") + return + end + + if (not next (data)) then + --> build data table for the character class + local _, unitClass = UnitClass ("player") + if (unitClass) then + local specIds = DF:GetClassSpecIDs (unitClass) + if (specIds) then + for _, specId in ipairs (specIds) do + data [specId] = {} + end + end + end + end + + new_keybind_frame.Data = data + new_keybind_frame.SetData = keybind_set_data + + new_keybind_frame.EditingSpec = DF:GetCurrentSpec() + new_keybind_frame.CurrentKeybindEditingSet = new_keybind_frame.Data [new_keybind_frame.EditingSpec] + + local allSpecButtons = {} + local switch_spec = function (self, button, specID) + new_keybind_frame.EditingSpec = specID + new_keybind_frame.CurrentKeybindEditingSet = new_keybind_frame.Data [specID] + + for _, button in ipairs (allSpecButtons) do + button.selectedTexture:Hide() + end + self.MyObject.selectedTexture:Show() + + --feedback ao jogador uma vez que as keybinds podem ter o mesmo valor + C_Timer.After (.04, function() new_keybind_frame:Hide() end) + C_Timer.After (.06, function() new_keybind_frame:Show() end) + + --atualiza a scroll + keybindScroll:UpdateScroll() + end + + --choose which spec to use + local spec1 = DF:CreateButton (new_keybind_frame, switch_spec, 160, 20, "Spec1 Placeholder Text", 1, _, _, "SpecButton1", _, 0, options_button_template, options_text_template) + local spec2 = DF:CreateButton (new_keybind_frame, switch_spec, 160, 20, "Spec2 Placeholder Text", 1, _, _, "SpecButton2", _, 0, options_button_template, options_text_template) + local spec3 = DF:CreateButton (new_keybind_frame, switch_spec, 160, 20, "Spec3 Placeholder Text", 1, _, _, "SpecButton3", _, 0, options_button_template, options_text_template) + local spec4 = DF:CreateButton (new_keybind_frame, switch_spec, 160, 20, "Spec4 Placeholder Text", 1, _, _, "SpecButton4", _, 0, options_button_template, options_text_template) + + --format the button label and icon with the spec information + local className, class = UnitClass ("player") + local i = 1 + local specIds = DF:GetClassSpecIDs (class) + + for index, specId in ipairs (specIds) do + local button = new_keybind_frame ["SpecButton" .. index] + local spec_id, spec_name, spec_description, spec_icon, spec_background, spec_role, spec_class = GetSpecializationInfoByID (specId) + button.text = spec_name + button:SetClickFunction (switch_spec, specId) + button:SetIcon (spec_icon) + button.specID = specId + + local selectedTexture = button:CreateTexture (nil, "background") + selectedTexture:SetAllPoints() + selectedTexture:SetColorTexture (1, 1, 1, 0.5) + if (specId ~= new_keybind_frame.EditingSpec) then + selectedTexture:Hide() + end + button.selectedTexture = selectedTexture + + tinsert (allSpecButtons, button) + i = i + 1 + end + + local specsTitle = DF:CreateLabel (new_keybind_frame, "Config keys for spec:", 12, "silver") + specsTitle:SetPoint ("topleft", new_keybind_frame, "topleft", 10, mainStartY) + + keybindScroll:SetPoint ("topleft", specsTitle.widget, "bottomleft", 0, -120) + + spec1:SetPoint ("topleft", specsTitle, "bottomleft", 0, -10) + spec2:SetPoint ("topleft", specsTitle, "bottomleft", 0, -30) + spec3:SetPoint ("topleft", specsTitle, "bottomleft", 0, -50) + if (class == "DRUID") then + spec4:SetPoint ("topleft", specsTitle, "bottomleft", 0, -70) + end + + local enter_the_key = CreateFrame ("frame", nil, new_keybind_frame) + enter_the_key:SetFrameStrata ("tooltip") + enter_the_key:SetSize (200, 60) + enter_the_key:SetBackdrop ({bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16, edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1}) + enter_the_key:SetBackdropColor (0, 0, 0, 1) + enter_the_key:SetBackdropBorderColor (1, 1, 1, 1) + enter_the_key.text = DF:CreateLabel (enter_the_key, "- Press a keyboard key to bind.\n- Click to bind a mouse button.\n- Press escape to cancel.", 11, "orange") + enter_the_key.text:SetPoint ("center", enter_the_key, "center") + enter_the_key:Hide() + + local registerKeybind = function (self, key) + if (ignoredKeys [key]) then + return + end + if (key == "ESCAPE") then + enter_the_key:Hide() + new_keybind_frame.IsListening = false + new_keybind_frame:SetScript ("OnKeyDown", nil) + return + end + + local bind = (IsShiftKeyDown() and "SHIFT-" or "") .. (IsControlKeyDown() and "CTRL-" or "") .. (IsAltKeyDown() and "ALT-" or "") + bind = bind .. key + + --adiciona para a tabela de keybinds + local keybind = new_keybind_frame.CurrentKeybindEditingSet [self.keybindIndex] + keybind.key = bind + + new_keybind_frame.IsListening = false + new_keybind_frame:SetScript ("OnKeyDown", nil) + + enter_the_key:Hide() + new_keybind_frame.keybindScroll:UpdateScroll() + + DF:QuickDispatch (callback) + end + + local set_keybind_key = function (self, button, keybindIndex) + if (new_keybind_frame.IsListening) then + key = mouseKeys [button] or button + return registerKeybind (new_keybind_frame, key) + end + new_keybind_frame.IsListening = true + new_keybind_frame.keybindIndex = keybindIndex + new_keybind_frame:SetScript ("OnKeyDown", registerKeybind) + + enter_the_key:Show() + enter_the_key:SetPoint ("bottom", self, "top") + end + + local new_key_bind = function (self, button, specID) + tinsert (new_keybind_frame.CurrentKeybindEditingSet, {key = "-none-", action = "_target", actiontext = ""}) + FauxScrollFrame_SetOffset (new_keybind_frame.keybindScroll, max (#new_keybind_frame.CurrentKeybindEditingSet-SCROLL_ROLL_AMOUNT, 0)) + new_keybind_frame.keybindScroll:UpdateScroll() + end + + local set_action_text = function (keybindIndex, _, text) + local keybind = new_keybind_frame.CurrentKeybindEditingSet [keybindIndex] + keybind.actiontext = text + DF:QuickDispatch (callback) + end + + local set_action_on_espace_press = function (textentry, capsule) + capsule = capsule or textentry.MyObject + local keybind = new_keybind_frame.CurrentKeybindEditingSet [capsule.CurIndex] + textentry:SetText (keybind.actiontext) + DF:QuickDispatch (callback) + end + + local lock_textentry = { + ["_target"] = true, + ["_taunt"] = true, + ["_interrupt"] = true, + ["_dispel"] = true, + ["_spell"] = false, + ["_macro"] = false, + } + + local change_key_action = function (self, keybindIndex, value) + local keybind = new_keybind_frame.CurrentKeybindEditingSet [keybindIndex] + keybind.action = value + new_keybind_frame.keybindScroll:UpdateScroll() + DF:QuickDispatch (callback) + end + local fill_action_dropdown = function() + + local locClass, class = UnitClass ("player") + + local taunt = "" + local interrupt = "" + local dispel = "" + + if (type (dispel) == "table") then + local dispelString = "\n" + for specID, spellid in pairs (dispel) do + local specid, specName = GetSpecializationInfoByID (specID) + local spellName = GetSpellInfo (spellid) + dispelString = dispelString .. "|cFFE5E5E5" .. specName .. "|r: |cFFFFFFFF" .. spellName .. "\n" + end + dispel = dispelString + else + dispel = "" + end + + return { + --{value = "_target", label = "Target", onclick = change_key_action, desc = "Target the unit"}, + --{value = "_taunt", label = "Taunt", onclick = change_key_action, desc = "Cast the taunt spell for your class\n\n|cFFFFFFFFSpell: " .. taunt}, + --{value = "_interrupt", label = "Interrupt", onclick = change_key_action, desc = "Cast the interrupt spell for your class\n\n|cFFFFFFFFSpell: " .. interrupt}, + --{value = "_dispel", label = "Dispel", onclick = change_key_action, desc = "Cast the interrupt spell for your class\n\n|cFFFFFFFFSpell: " .. dispel}, + {value = "_spell", label = "Cast Spell", onclick = change_key_action, desc = "Type the spell name in the text box"}, + {value = "_macro", label = "Run Macro", onclick = change_key_action, desc = "Type your macro in the text box"}, + } + end + + local copy_keybind = function (self, button, keybindIndex) + local keybind = new_keybind_frame.CurrentKeybindEditingSet [keybindIndex] + for specID, t in pairs (new_keybind_frame.Data) do + if (specID ~= new_keybind_frame.EditingSpec) then + local key = CopyTable (keybind) + local specid, specName = GetSpecializationInfoByID (specID) + tinsert (new_keybind_frame.Data [specID], key) + DF:Msg ("Keybind copied to " .. specName) + end + end + DF:QuickDispatch (callback) + end + + local delete_keybind = function (self, button, keybindIndex) + tremove (new_keybind_frame.CurrentKeybindEditingSet, keybindIndex) + new_keybind_frame.keybindScroll:UpdateScroll() + DF:QuickDispatch (callback) + end + + local newTitle = DF:CreateLabel (new_keybind_frame, "Create a new Keybind:", 12, "silver") + newTitle:SetPoint ("topleft", new_keybind_frame, "topleft", 200, mainStartY) + local createNewKeybind = DF:CreateButton (new_keybind_frame, new_key_bind, 160, 20, "New Key Bind", 1, _, _, "NewKeybindButton", _, 0, options_button_template, options_text_template) + createNewKeybind:SetPoint ("topleft", newTitle, "bottomleft", 0, -10) + --createNewKeybind:SetIcon ([[Interface\Buttons\UI-GuildButton-PublicNote-Up]]) + + local update_keybind_list = function (self) + + local keybinds = new_keybind_frame.CurrentKeybindEditingSet + FauxScrollFrame_Update (self, #keybinds, SCROLL_ROLL_AMOUNT, 21) + local offset = FauxScrollFrame_GetOffset (self) + + for i = 1, SCROLL_ROLL_AMOUNT do + local index = i + offset + local f = self.Frames [i] + local data = keybinds [index] + + if (data) then + --index + f.Index.text = index + --keybind + local keyBindText = keysToMouse [data.key] or data.key + + keyBindText = keyBindText:gsub ("type1", "LeftButton") + keyBindText = keyBindText:gsub ("type2", "RightButton") + keyBindText = keyBindText:gsub ("type3", "MiddleButton") + + f.KeyBind.text = keyBindText + f.KeyBind:SetClickFunction (set_keybind_key, index, nil, "left") + f.KeyBind:SetClickFunction (set_keybind_key, index, nil, "right") + --action + f.ActionDrop:SetFixedParameter (index) + f.ActionDrop:Select (data.action) + --action text + f.ActionText.text = data.actiontext + f.ActionText:SetEnterFunction (set_action_text, index) + f.ActionText.CurIndex = index + + if (lock_textentry [data.action]) then + f.ActionText:Disable() + else + f.ActionText:Enable() + end + + --copy + f.Copy:SetClickFunction (copy_keybind, index) + --delete + f.Delete:SetClickFunction (delete_keybind, index) + + f:Show() + else + f:Hide() + end + end + + self:Show() + end + + + + keybindScroll:SetScript ("OnVerticalScroll", function (self, offset) + FauxScrollFrame_OnVerticalScroll (self, offset, 21, update_keybind_list) + end) + keybindScroll.UpdateScroll = update_keybind_list + + local backdropColor = {.3, .3, .3, .3} + local backdropColorOnEnter = {.6, .6, .6, .6} + local on_enter = function (self) + self:SetBackdropColor (unpack (backdropColorOnEnter)) + end + local on_leave = function (self) + self:SetBackdropColor (unpack (backdropColor)) + end + + local font = "GameFontHighlightSmall" + + for i = 1, SCROLL_ROLL_AMOUNT do + local f = CreateFrame ("frame", "$KeyBindFrame" .. i, keybindScroll) + f:SetSize (1009, 20) + f:SetPoint ("topleft", keybindScroll, "topleft", 0, -(i-1)*29) + f:SetBackdrop ({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true}) + f:SetBackdropColor (unpack (backdropColor)) + f:SetScript ("OnEnter", on_enter) + f:SetScript ("OnLeave", on_leave) + tinsert (keybindScroll.Frames, f) + + f.Index = DF:CreateLabel (f, "1") + f.KeyBind = DF:CreateButton (f, set_key_bind, 100, 20, "", _, _, _, "SetNewKeybindButton", _, 0, options_button_template, options_text_template) + f.ActionDrop = DF:CreateDropDown (f, fill_action_dropdown, 0, 120, 20, "ActionDropdown", _, options_dropdown_template) + f.ActionText = DF:CreateTextEntry (f, function()end, 660, 20, "TextBox", _, _, options_dropdown_template) + f.Copy = DF:CreateButton (f, copy_keybind, 20, 20, "", _, _, _, "CopyKeybindButton", _, 0, options_button_template, options_text_template) + f.Delete = DF:CreateButton (f, delete_keybind, 16, 20, "", _, _, _, "DeleteKeybindButton", _, 2, options_button_template, options_text_template) + + f.Index:SetPoint ("left", f, "left", 10, 0) + f.KeyBind:SetPoint ("left", f, "left", 43, 0) + f.ActionDrop:SetPoint ("left", f, "left", 150, 0) + f.ActionText:SetPoint ("left", f, "left", 276, 0) + f.Copy:SetPoint ("left", f, "left", 950, 0) + f.Delete:SetPoint ("left", f, "left", 990, 0) + + f.Copy:SetIcon ([[Interface\Buttons\UI-GuildButton-PublicNote-Up]], nil, nil, nil, nil, nil, nil, 4) + f.Delete:SetIcon ([[Interface\Buttons\UI-StopButton]], nil, nil, nil, nil, nil, nil, 4) + + f.Copy.tooltip = "copy this keybind to other specs" + f.Delete.tooltip = "erase this keybind" + + --editbox + f.ActionText:SetJustifyH ("left") + f.ActionText:SetHook ("OnEscapePressed", set_action_on_espace_press) + f.ActionText:SetHook ("OnEditFocusGained", function() + local playerSpells = {} + local tab, tabTex, offset, numSpells = GetSpellTabInfo (2) + for i = 1, numSpells do + local index = offset + i + local spellType, spellId = GetSpellBookItemInfo (index, "player") + if (spellType == "SPELL") then + local spellName = GetSpellInfo (spellId) + tinsert (playerSpells, spellName) + end + end + f.ActionText.WordList = playerSpells + end) + + f.ActionText:SetAsAutoComplete ("WordList") + end + + local header = CreateFrame ("frame", "$parentOptionsPanelFrameHeader", keybindScroll) + header:SetPoint ("bottomleft", keybindScroll, "topleft", 0, 2) + header:SetPoint ("bottomright", keybindScroll, "topright", 0, 2) + header:SetHeight (16) + + header.Index = DF:CreateLabel (header, "Index", DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE")) + header.Key = DF:CreateLabel (header, "Key", DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE")) + header.Action = DF:CreateLabel (header, "Action", DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE")) + header.Macro = DF:CreateLabel (header, "Spell Name / Macro", DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE")) + header.Copy = DF:CreateLabel (header, "Copy", DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE")) + header.Delete = DF:CreateLabel (header, "Delete", DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE")) + + header.Index:SetPoint ("left", header, "left", 10, 0) + header.Key:SetPoint ("left", header, "left", 43, 0) + header.Action:SetPoint ("left", header, "left", 150, 0) + header.Macro:SetPoint ("left", header, "left", 276, 0) + header.Copy:SetPoint ("left", header, "left", 950, 0) + header.Delete:SetPoint ("left", header, "left", 990, 0) + + new_keybind_frame:SetScript ("OnShow", function() + + --new_keybind_frame.EditingSpec = EnemyGrid.CurrentSpec + --new_keybind_frame.CurrentKeybindEditingSet = EnemyGrid.CurrentKeybindSet + + for _, button in ipairs (allSpecButtons) do + if (new_keybind_frame.EditingSpec ~= button.specID) then + button.selectedTexture:Hide() + else + button.selectedTexture:Show() + end + end + + keybindScroll:UpdateScroll() + end) + + new_keybind_frame:SetScript ("OnHide", function() + if (new_keybind_frame.IsListening) then + new_keybind_frame.IsListening = false + new_keybind_frame:SetScript ("OnKeyDown", nil) + end + end) + + return new_keybind_frame +end + +function DF:BuildKeybindFunctions (data, prefix) + + --~keybind + local classLoc, class = UnitClass ("player") + local bindingList = data + + local bindString = "self:ClearBindings();" + local bindKeyBindTypeFunc = [[local unitFrame = ...;]] + local bindMacroTextFunc = [[local unitFrame = ...;]] + local isMouseBinding + + for i = 1, #bindingList do + local bind = bindingList [i] + local bindType + + --which button to press + if (bind.key:find ("type")) then + local keyNumber = tonumber (bind.key:match ("%d")) + bindType = keyNumber + isMouseBinding = true + else + bindType = prefix .. "" .. i + bindString = bindString .. "self:SetBindingClick (0, '" .. bind.key .. "', self:GetName(), '" .. bindType .. "');" + bindType = "-" .. prefix .. "" .. i + isMouseBinding = nil + end + + --keybind type + local shift, alt, ctrl = bind.key:match ("SHIFT"), bind.key:match ("ALT"), bind.key:match ("CTRL") + local CommandKeys = alt and alt .. "-" or "" + CommandKeys = ctrl and CommandKeys .. ctrl .. "-" or CommandKeys + CommandKeys = shift and CommandKeys .. shift .. "-" or CommandKeys + + local keyBindType + if (isMouseBinding) then + keyBindType = [[unitFrame:SetAttribute ("@COMMANDtype@BINDTYPE", "macro");]] + else + keyBindType = [[unitFrame:SetAttribute ("type@BINDTYPE", "macro");]] + end + + keyBindType = keyBindType:gsub ("@BINDTYPE", bindType) + keyBindType = keyBindType:gsub ("@COMMAND", CommandKeys) + bindKeyBindTypeFunc = bindKeyBindTypeFunc .. keyBindType + + --spell or macro + if (bind.action == "_spell") then + local macroTextLine + if (isMouseBinding) then + macroTextLine = [[unitFrame:SetAttribute ("@COMMANDmacrotext@BINDTYPE", "/cast [@mouseover] @SPELL");]] + else + macroTextLine = [[unitFrame:SetAttribute ("macrotext@BINDTYPE", "/cast [@mouseover] @SPELL");]] + end + macroTextLine = macroTextLine:gsub ("@BINDTYPE", bindType) + macroTextLine = macroTextLine:gsub ("@SPELL", bind.actiontext) + macroTextLine = macroTextLine:gsub ("@COMMAND", CommandKeys) + bindMacroTextFunc = bindMacroTextFunc .. macroTextLine + + elseif (bind.action == "_macro") then + local macroTextLine + if (isMouseBinding) then + macroTextLine = [[unitFrame:SetAttribute ("@COMMANDmacrotext@BINDTYPE", "@MACRO");]] + else + macroTextLine = [[unitFrame:SetAttribute ("macrotext@BINDTYPE", "@MACRO");]] + end + macroTextLine = macroTextLine:gsub ("@BINDTYPE", bindType) + macroTextLine = macroTextLine:gsub ("@MACRO", bind.actiontext) + macroTextLine = macroTextLine:gsub ("@COMMAND", CommandKeys) + bindMacroTextFunc = bindMacroTextFunc .. macroTextLine + + end + end + + --~key + local bindTypeFuncLoaded = loadstring (bindKeyBindTypeFunc) + local bindMacroFuncLoaded = loadstring (bindMacroTextFunc) + + if (not bindMacroFuncLoaded or not bindTypeFuncLoaded) then + return + end + + return bindString, bindTypeFuncLoaded, bindMacroFuncLoaded +end + + +function DF:SetKeybindsOnProtectedFrame (frame, bind_string, bind_type_func, bind_macro_func) + + bind_type_func (frame) + bind_macro_func (frame) + frame:SetAttribute ("_onenter", bind_string) + +end + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +-- ~standard backdrop + +function DF:ApplyStandardBackdrop (f, darkTheme, alphaScale) + alphaScale = alphaScale or 1.0 + + if (darkTheme) then + f:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Cooldown\cooldown2]], tileSize = 32, tile = true}) + f:SetBackdropBorderColor (0, 0, 0, 1) + f:SetBackdropColor (.54, .54, .54, .54 * alphaScale) + else + f:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true}) + f:SetBackdropBorderColor (0, 0, 0, 1) + f:SetBackdropColor (0, 0, 0, 0.2 * alphaScale) + end + + if (not f.__background) then + f.__background = f:CreateTexture (nil, "background") + end + + f.__background:SetColorTexture (0.2317647, 0.2317647, 0.2317647) + f.__background:SetVertexColor (0.27, 0.27, 0.27) + f.__background:SetAlpha (0.8 * alphaScale) + f.__background:SetVertTile (true) + f.__background:SetHorizTile (true) + f.__background:SetAllPoints() +end + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +-- ~title bar + +DF.TitleFunctions = { + + SetTitle = function (self, titleText, titleColor, font, size) + self.TitleLabel:SetText (titleText or self.TitleLabel:GetText()) + + if (titleColor) then + local r, g, b, a = DF:ParseColors (titleColor) + self.TitleLabel:SetTextColor (r, g, b, a) + end + + if (font) then + DF:SetFontFace (self.TitleLabel, font) + end + + if (size) then + DF:SetFontSize (self.TitleLabel, size) + end + end + + +} + +function DF:CreateTitleBar (f, titleText) + + local titleBar = CreateFrame ("frame", f:GetName() and f:GetName() .. "TitleBar" or nil, f) + titleBar:SetPoint ("topleft", f, "topleft", 2, -3) + titleBar:SetPoint ("topright", f, "topright", -2, -3) + titleBar:SetHeight (20) + titleBar:SetBackdrop (SimplePanel_frame_backdrop) --it's an upload from this file + titleBar:SetBackdropColor (.2, .2, .2, 1) + titleBar:SetBackdropBorderColor (0, 0, 0, 1) + + local closeButton = CreateFrame ("button", titleBar:GetName() and titleBar:GetName() .. "CloseButton" or nil, titleBar) + closeButton:SetSize (16, 16) + closeButton:SetNormalTexture (DF.folder .. "icons") + closeButton:SetHighlightTexture (DF.folder .. "icons") + closeButton:SetPushedTexture (DF.folder .. "icons") + closeButton:GetNormalTexture():SetTexCoord (0, 16/128, 0, 1) + closeButton:GetHighlightTexture():SetTexCoord (0, 16/128, 0, 1) + closeButton:GetPushedTexture():SetTexCoord (0, 16/128, 0, 1) + closeButton:SetAlpha (0.7) + closeButton:SetScript ("OnClick", simple_panel_close_click) --upvalue from this file + + local titleLabel = titleBar:CreateFontString (titleBar:GetName() and titleBar:GetName() .. "TitleText" or nil, "overlay", "GameFontNormal") + titleLabel:SetTextColor (.8, .8, .8, 1) + titleLabel:SetText (titleText or "") + + --anchors + closeButton:SetPoint ("right", titleBar, "right", -2, 0) + titleLabel:SetPoint ("center", titleBar, "center") + + --members + f.TitleBar = titleBar + f.CloseButton = closeButton + f.TitleLabel = titleLabel + + DF:Mixin (f, DF.TitleFunctions) + + return titleBar +end + + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +-- ~icon row + +DF.IconRowFunctions = { + + GetIcon = function (self) + local iconFrame = self.IconPool [self.NextIcon] + + if (not iconFrame) then + local newIconFrame = CreateFrame ("cooldown", "$parentIconCooldown" .. self.NextIcon, self, "CooldownFrameTemplate") + newIconFrame:SetSize (self.options.icon_width, self.options.icon_height) + + newIconFrame.Texture = newIconFrame:CreateTexture (nil, "background") + newIconFrame.Texture:SetAllPoints() + + newIconFrame.Text = newIconFrame:CreateFontString (nil, "overlay", "GameFontNormal") + newIconFrame.Text:SetPoint ("center") + newIconFrame.Text:Hide() + + newIconFrame:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1}) + newIconFrame:SetBackdropBorderColor (0, 0, 0, 0) + newIconFrame:EnableMouse (false) + + self.IconPool [self.NextIcon] = newIconFrame + iconFrame = newIconFrame + end + + iconFrame:ClearAllPoints() + + local anchor = self.options.anchor + local anchorTo = self.NextIcon == 1 and self or self.IconPool [self.NextIcon - 1] + local xPadding = self.NextIcon == 1 and self.options.left_padding or self.options.icon_padding + local growDirection = self.options.grow_direction + + if (growDirection == 1) then --grow to right + if (self.NextIcon == 1) then + iconFrame:SetPoint ("left", anchorTo, "left", xPadding, 0) + else + iconFrame:SetPoint ("left", anchorTo, "right", xPadding, 0) + end + + elseif (growDirection == 2) then --grow to left + if (self.NextIcon == 1) then + iconFrame:SetPoint ("right", anchorTo, "right", xPadding, 0) + else + iconFrame:SetPoint ("right", anchorTo, "left", xPadding, 0) + end + + end + + DF:SetFontColor (iconFrame.Text, self.options.text_color) + + self.NextIcon = self.NextIcon + 1 + return iconFrame + end, + + SetIcon = function (self, spellId, borderColor, startTime, duration) + local spellName, _, spellIcon = GetSpellInfo (spellId) + + if (spellIcon) then + local iconFrame = self:GetIcon() + iconFrame.Texture:SetTexture (spellIcon) + iconFrame.Texture:SetTexCoord (unpack (self.options.texcoord)) + + if (borderColor) then + iconFrame:SetBackdropBorderColor (Plater:ParseColors (borderColor)) + else + iconFrame:SetBackdropBorderColor (0, 0, 0 ,0) + end + + if (startTime) then + CooldownFrame_Set (iconFrame, startTime, duration, true, true) + + if (self.options.show_text) then + iconFrame.Text:Show() + iconFrame.Text:SetText (floor (startTime + duration - GetTime())) + else + iconFrame.Text:Hide() + end + else + iconFrame.Text:Hide() + end + + iconFrame:Show() + + --> update the size of the frame + self:SetWidth ((self.options.left_padding * 2) + (self.options.icon_padding * (self.NextIcon-2)) + (self.options.icon_width * (self.NextIcon - 1))) + + --> show the frame + self:Show() + + return iconFrame + end + end, + + ClearIcons = function (self) + for i = 1, self.NextIcon -1 do + self.IconPool [i]:Hide() + end + self.NextIcon = 1 + self:Hide() + end, + + GetIconGrowDirection = function (self) + local side = self.options.anchor.side + + if (side == 1) then + return 1 + elseif (side == 2) then + return 2 + elseif (side == 3) then + return 1 + elseif (side == 4) then + return 1 + elseif (side == 5) then + return 2 + elseif (side == 6) then + return 1 + elseif (side == 7) then + return 2 + elseif (side == 8) then + return 1 + elseif (side == 9) then + return 1 + elseif (side == 10) then + return 1 + elseif (side == 11) then + return 2 + elseif (side == 12) then + return 1 + elseif (side == 13) then + return 1 + end + end +} + +local default_icon_row_options = { + icon_width = 20, + icon_height = 20, + texcoord = {.1, .9, .1, .9}, + show_text = true, + text_color = {1, 1, 1, 1}, + left_padding = 2, --distance between right and left + top_padding = 2, --distance between top and bottom + icon_padding = 2, --distance between each icon + backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true}, + backdrop_color = {0, 0, 0, 0.5}, + backdrop_border_color = {0, 0, 0, 1}, + anchor = {side = 6, x = 2, y = 0}, + grow_direction = 1, --1 = to right 2 = to left +} + +function DF:CreateIconRow (parent, name, options) + local f = CreateFrame ("frame", name, parent) + f.IconPool = {} + f.NextIcon = 1 + + DF:Mixin (f, DF.IconRowFunctions) + DF:Mixin (f, DF.OptionsFunctions) + + f:BuildOptionsTable (default_icon_row_options, options) + + f:SetSize (f.options.icon_width, f.options.icon_height + (f.options.top_padding * 2)) + f:SetBackdrop (f.options.backdrop) + f:SetBackdropColor (unpack (f.options.backdrop_color)) + f:SetBackdropBorderColor (unpack (f.options.backdrop_border_color)) + + return f +end
