diff --git a/PerfectRaid_Frames.lua b/PerfectRaid_Frames.lua
new file mode 100644
index 0000000..cf88092
--- /dev/null
+++ b/PerfectRaid_Frames.lua
@@ -0,0 +1,482 @@
+--[[-------------------------------------------------------------------------
+ Copyright (c) 2006, Jim Whitehead II <cladhaire@gmail.com>
+ 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 PerfectRaid 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.
+---------------------------------------------------------------------------]]
+
+local Frames = PerfectRaid:NewModule("PerfectRaid-Frames")
+local L = PerfectRaidLocals
+local utils = DongleStub("DongleUtils")
+local frames
+
+function Frames:Initialize()
+ frames = PerfectRaid.frames
+end
+
+function Frames:Enable()
+end
+
+function Frames:ConfigureButton(button)
+end
+
+function Frames:ShowButton(button)
+end
+
+function Frames:CreateOptions(opt)
+ self.options = opt
+ local options = CreateFrame("Frame", "PROptions_Frames", PROptions)
+ opt:AddOptionsTab(L["Raid Frames"], options)
+
+ local num_entries = 15
+ local scrollframe = opt:CreateListFrame(options, num_entries)
+
+ local update = function()
+ local list = PerfectRaid.db.profile.headers
+
+ local idx,button
+ local offset = FauxScrollFrame_GetOffset(scrollframe)
+ FauxScrollFrame_Update(scrollframe, #list, 15, 20)
+ for i=1,num_entries do
+ idx = offset + i
+ button = scrollframe.entries[i]
+ if idx <= #list then
+ local entry = list[idx]
+ local display = entry.name
+ button.line1:SetText(display)
+ button:Show()
+ if scrollframe.selected == idx then
+ button:SetChecked(true)
+ else
+ button:SetChecked(false)
+ end
+ else
+ button:Hide()
+ end
+ end
+ end
+
+ scrollframe.update = update
+
+ scrollframe:SetScript("OnVerticalScroll", function()
+ FauxScrollFrame_OnVerticalScroll(20, update)
+ self:EnableButtons()
+ end)
+ scrollframe:SetScript("OnShow", function()
+ scrollframe.update()
+ self:EnableButtons()
+ end)
+
+ local postClick = function()
+ self:EnableButtons()
+ end
+
+ for i,frame in ipairs(scrollframe.entries) do
+ frame:SetScript("PostClick", postClick)
+ end
+
+ local delete = CreateFrame("Button", "PRFrames_Delete", options, "PRButtonTemplate")
+ delete:SetText(L["Delete"])
+ delete:SetPoint("BOTTOMRIGHT", 0, 5)
+ delete:SetScript("OnClick", function() self:DeleteEntry() end)
+ delete:Show()
+
+ local edit = CreateFrame("Button", "PRFrames_Edit", options, "PRButtonTemplate")
+ edit:SetText(L["Edit"])
+ edit:SetPoint("BOTTOMRIGHT", delete, "BOTTOMLEFT", -10, 0)
+ edit:SetScript("OnClick", function() self:EditEntry() end)
+ edit:Show()
+
+ local add = CreateFrame("Button", "PRFrames_Add", options, "PRButtonTemplate")
+ add:SetText(L["Add"])
+ add:SetPoint("BOTTOMRIGHT", edit, "BOTTOMLEFT", -10, 0)
+ add:SetScript("OnClick", function() self:AddEntry() end)
+ add:Show()
+
+ --self:CreateEditFrame(options)
+end
+
+
+function Frames:CreateEditFrame(parent)
+ local frame = CreateFrame("Frame", "PROptions_Buffs_Edit", PROptions)
+ local name = "PROptions_Buffs_Edit"
+ frame:SetAllPoints(PROptions_Buffs)
+ frame:Hide()
+
+ local buffname = CreateFrame("EditBox", name.."BuffName", frame, "InputBoxTemplate")
+ local font = buffname:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
+ font:SetText(L["Buff Name:"])
+ font:SetPoint("BOTTOMLEFT", buffname, "TOPLEFT", 0, 3)
+ buffname:SetPoint("TOPLEFT", 0, -10)
+ buffname:SetAutoFocus(nil)
+ buffname:SetWidth(180)
+ buffname:SetHeight(20)
+ buffname:Show()
+ frame.buffname = buffname
+
+ local groupname = CreateFrame("EditBox", name.."GroupName", frame, "InputBoxTemplate")
+ local font = groupname:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
+ font:SetText(L["Group Buff Name:"])
+ font:SetPoint("BOTTOMLEFT", groupname, "TOPLEFT", 0, 3)
+ groupname:SetPoint("TOPLEFT", 220, -10)
+ groupname:SetAutoFocus(nil)
+ groupname:SetWidth(180)
+ groupname:SetHeight(20)
+ groupname:Show()
+ frame.groupname = groupname
+
+ local disptext = CreateFrame("EditBox", name.."DispText", frame, "InputBoxTemplate")
+ local font = disptext:CreateFontString(nil, "ARTWORK", "GameFontHighlightSmall")
+ font:SetText(L["Display Text:"])
+ font:SetPoint("BOTTOMLEFT", disptext, "TOPLEFT", 0, 3)
+ disptext:SetPoint("TOPLEFT", 0, -50)
+ disptext:SetAutoFocus(nil)
+ disptext:SetWidth(180)
+ disptext:SetHeight(20)
+ disptext:Show()
+ frame.disptext = disptext
+
+ -- Color Swatch
+ local function colorSwatchCancel()
+ local self = ColorPickerFrame.object;
+ local r, g, b = self.r, self.g, self.b;
+ self.normalTexture:SetVertexColor(r, g, b);
+ end
+
+ local function colorSwatchColor()
+ local self = ColorPickerFrame.object;
+ local r, g, b = ColorPickerFrame:GetColorRGB();
+ self.normalTexture:SetVertexColor(r, g, b);
+ self.color[1] = r
+ self.color[2] = g
+ self.color[3] = b
+ disptext:SetTextColor(r,g,b)
+ end
+
+ local function colorSwatchOpacity()
+ local self = ColorPickerFrame.object;
+ local a = OpacitySliderFrame:GetValue();
+ end
+
+ local function colorSwatchShow(self)
+ local r, g, b, a;
+ self.color = self.color or {1,1,1}
+
+ local color = self.color;
+ if ( color ) then
+ r, g, b, a = unpack(color);
+ end
+
+ self.r, self.g, self.b = r, g, b
+ self.opacityFunc = colorSwatchOpacity;
+ self.swatchFunc = colorSwatchColor;
+ self.cancelFunc = colorSwatchCancel;
+
+ ColorPickerFrame.object = self;
+ UIDropDownMenuButton_OpenColorPicker(self);
+ ColorPickerFrame:SetFrameStrata("TOOLTIP");
+ ColorPickerFrame:Raise();
+ end
+
+ local function colorSwatchOnClick(self)
+ CloseMenus();
+ colorSwatchShow(self);
+ end
+
+ local function colorSwatchOnEnter(self)
+ self.bg:SetVertexColor(1, 0.82, 0);
+ end
+
+ local function colorSwatchOnLeave(self)
+ self.bg:SetVertexColor(1, 1, 1);
+ end
+
+ local swatch = CreateFrame("Button", "PRColorSelect", frame);
+ swatch:SetHeight(20) swatch:SetWidth(20)
+ swatch:SetPoint("LEFT", disptext, "RIGHT", 5, 0)
+ local bg = swatch:CreateTexture(nil, "BACKGROUND");
+ local normalTexture = swatch:CreateTexture(nil, "ARTWORK");
+ frame.color = swatch
+
+ normalTexture:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch");
+ normalTexture:SetAllPoints(swatch);
+ swatch:SetNormalTexture(normalTexture);
+ bg:SetTexture(.2,.2,.2);
+ bg:SetPoint("TOPLEFT", swatch, 1, -1);
+ bg:SetPoint("BOTTOMRIGHT", swatch, 0, 1);
+
+ normalTexture:SetVertexColor(1,1,1)
+
+ swatch.bg, swatch.normalTexture = bg, normalTexture;
+ swatch.object, swatch.hasAlpha = self, 1
+
+ swatch:SetScript("OnLeave", colorSwatchOnLeave);
+ swatch:SetScript("OnEnter", colorSwatchOnEnter);
+ swatch:SetScript("OnClick", colorSwatchOnClick);
+
+ buffname:SetScript("OnTabPressed", function() if IsShiftKeyDown() then disptext:SetFocus() else groupname:SetFocus() end end)
+ groupname:SetScript("OnTabPressed", function() if IsShiftKeyDown() then buffname:SetFocus() else disptext:SetFocus() end end)
+ disptext:SetScript("OnTabPressed", function() if IsShiftKeyDown() then groupname:SetFocus() else buffname:SetFocus() end end)
+
+ local function makeCheck(value)
+ local button = CreateFrame("CheckButton", "PRBuffCond_"..value, PROptions_Buffs_Edit, "PRCheckTemplate")
+ button.Label:SetText(value)
+ button.value = value
+ return button
+ end
+
+ PROptions_Buffs_Edit.checks = {}
+ local checks = PROptions_Buffs_Edit.checks
+
+ -- Build condition checkboxes
+
+ checks[1] = makeCheck(self.conditions[1])
+ checks[1]:SetPoint("TOPLEFT", disptext, "BOTTOMLEFT", 0, -20)
+ checks[1]:Show()
+
+ for i=2,6 do
+ checks[i] = makeCheck(self.conditions[i])
+ checks[i]:SetPoint("TOPLEFT", checks[i-1], "TOPRIGHT", 60, 0)
+ checks[i]:Show()
+ end
+
+ checks[7] = makeCheck(self.conditions[7])
+ checks[7]:SetPoint("TOPLEFT", checks[1], "BOTTOMLEFT", 0, -10)
+ checks[7]:Show()
+
+ for i=8,12 do
+ checks[i] = makeCheck(self.conditions[i])
+ checks[i]:SetPoint("TOPLEFT", checks[i-1], "TOPRIGHT", 60, 0)
+ checks[i]:Show()
+ end
+
+ checks[13] = makeCheck(self.conditions[13])
+ checks[13]:SetPoint("TOPLEFT", checks[7], "BOTTOMLEFT", 0, -10)
+ checks[13]:Show()
+
+ for i=14,18 do
+ checks[i] = makeCheck(self.conditions[i])
+ checks[i]:SetPoint("TOPLEFT", checks[i-1], "TOPRIGHT", 60, 0)
+ checks[i]:Show()
+ end
+
+ checks[19] = makeCheck(self.conditions[19])
+ checks[19]:SetPoint("TOPLEFT", checks[13], "BOTTOMLEFT", 0, -10)
+ checks[19]:Show()
+
+ for i=20,21 do
+ checks[i] = makeCheck(self.conditions[i])
+ checks[i]:SetPoint("TOPLEFT", checks[i-1], "TOPRIGHT", 60, 0)
+ checks[i]:Show()
+ end
+
+ local cancel = CreateFrame("Button", "PRBuffs_EditCancel", PROptions_Buffs_Edit, "PRButtonTemplate")
+ cancel:SetText(L["Cancel"])
+ cancel:SetPoint("BOTTOMRIGHT", 0, 5)
+ cancel:SetScript("OnClick", function() self:CancelEntry() end)
+ cancel:Show()
+
+ local save = CreateFrame("Button", "PRBuffs_EditSave", PROptions_Buffs_Edit, "PRButtonTemplate")
+ save:SetText(L["Save"])
+ save:SetPoint("BOTTOMRIGHT", cancel, "BOTTOMLEFT", -10, 0)
+ save:SetScript("OnClick", function() self:SaveEntry() end)
+ save:Show()
+
+ local missing = CreateFrame("CheckButton", "PRBuffs_Missing", PROptions_Buffs_Edit, "PRCheckTemplate")
+ missing.Label:SetText(L["Only show if this buff is missing"])
+ missing:SetPoint("BOTTOMLEFT", 0, 10)
+ missing:Show()
+ frame.missing = missing
+
+ local disabled = CreateFrame("CheckButton", "PRBuffs_Disabled", PROptions_Buffs_Edit, "PRCheckTemplate")
+ disabled.Label:SetText(L["Do not check this buff (Disable)"])
+ disabled:SetPoint("BOTTOMLEFT", missing, "TOPLEFT", 0, 10)
+ disabled:Show()
+ frame.disabled = disabled
+end
+
+function Frames:EditEntry()
+ local scrollframe = PROptions_BuffsScrollFrame
+ local offset = FauxScrollFrame_GetOffset(scrollframe)
+ local selected = PROptions_Buffs.selected
+ local entry = PerfectRaid.db.profile.buffs[selected]
+
+ local options = PROptions_Buffs_Edit
+ options.editEntry = entry
+
+ self.options:FadeOut(PROptions_Buffs)
+ self.options:FadeIn(options)
+ options.buffname:SetText(entry.buffname)
+ options.groupname:SetText(entry.groupname or "")
+ options.disptext:SetText(entry.disptext)
+ options.disptext:SetTextColor(utils.HexToRGBPerc(entry.color))
+ PRColorSelect.normalTexture:SetVertexColor(utils.HexToRGBPerc(entry.color))
+
+ local cond = {string.split(",", entry.conds)}
+ for k,v in ipairs(cond) do
+ cond[v] = true
+ end
+ for idx,button in ipairs(PROptions_Buffs_Edit.checks) do
+ if cond[button.value] then
+ button:SetChecked(true)
+ else
+ button:SetChecked(false)
+ end
+ end
+
+ options.missing:SetChecked(entry.missing)
+ options.disabled:SetChecked(entry.disabled)
+end
+
+function Frames:AddEntry()
+ local options = PROptions_Buffs_Edit
+ self.options:FadeOut(PROptions_Buffs)
+ self.options:FadeIn(options)
+ options.buffname:SetText("")
+ options.groupname:SetText("")
+ options.disptext:SetText("")
+ options.disptext:SetTextColor(1,1,1)
+ PRColorSelect.normalTexture:SetVertexColor(1,1,1)
+
+ for idx,button in ipairs(PROptions_Buffs_Edit.checks) do
+ button:SetChecked(false)
+ end
+ options.missing:SetChecked(false)
+ options.disabled:SetChecked(false)
+ options.buffname:SetFocus()
+end
+
+function Frames:DeleteEntry()
+ local scrollframe = PROptions_BuffsScrollFrame
+ local offset = FauxScrollFrame_GetOffset(scrollframe)
+ local selected = PROptions_Buffs.selected
+ local idx = offset + selected
+ table.remove(PerfectRaid.db.profile.buffs, idx)
+ PROptions_Buffs.selected = nil
+ scrollframe.update()
+ self:EnableButtons()
+ self:UpdateBuffTable()
+end
+
+function Frames:UpdateBuffTable()
+ for k,v in pairs(buffs) do buffs[k] = nil end
+
+ for idx,entry in ipairs(PerfectRaid.db.profile.buffs) do
+ if not entry.disabled then
+ local tbl = {}
+ tbl.buffname = entry.buffname
+ tbl.groupname = entry.groupname
+ tbl.colortext = "|cFF"..entry.color..entry.disptext.."|r"
+ tbl.missing = entry.missing
+ tbl.cond = {string.split(",", entry.conds)}
+ table.insert(buffs, tbl)
+ end
+ end
+
+ for unit in pairs(frames) do
+ self:UNIT_AURA(nil, unit)
+ end
+end
+
+function Frames:SaveEntry()
+ local frame = PROptions_Buffs_Edit
+
+ local buffname = frame.buffname:GetText()
+ local groupname = frame.groupname:GetText()
+ local disptext = frame.disptext:GetText()
+
+ local err
+ if buffname == "" then
+ err = "You must supply a buff name"
+ elseif disptext == "" then
+ err = "You must supply a display text"
+ end
+
+ if err then
+ StaticPopupDialogs["PR_BUFF_SAVE_ERROR"].text = err
+ StaticPopup_Show("PR_BUFF_SAVE_ERROR")
+ return
+ end
+
+ local options = PROptions_Buffs_Edit
+ local entry = options.editEntry or {}
+
+ entry.buffname = buffname
+ entry.groupname = groupname
+ entry.disptext = disptext
+
+ local work = {}
+ for idx,button in ipairs(PROptions_Buffs_Edit.checks) do
+ if button:GetChecked() then
+ table.insert(work, button.value)
+ end
+ end
+
+ local conds = strjoin(",", unpack(work))
+ entry.conds = conds
+ entry.missing = frame.missing:GetChecked()
+ entry.disabled = frame.disabled:GetChecked()
+
+ local color = utils.RGBPercToHex(frame.disptext:GetTextColor())
+ entry.color = color
+ if not options.editEntry then
+ table.insert(PerfectRaid.db.profile.buffs, entry)
+ end
+
+ options.editEntry = nil
+
+ self:CancelEntry()
+ PROptions_BuffsScrollFrame.update()
+ self:UpdateBuffTable()
+end
+
+function Frames:CancelEntry()
+ local options = PROptions_Buffs_Edit
+ self.options:FadeOut(options)
+ options.editEntry = nil
+ self.options:FadeIn(PROptions_Buffs)
+end
+
+function Frames:EnableButtons()
+ local selected = PROptions_Frames.selected
+ if selected then
+ PRFrames_Edit:Enable()
+ PRFrames_Delete:Enable()
+ else
+ PRFrames_Edit:Disable()
+ PRFrames_Delete:Disable()
+ end
+end
+
+StaticPopupDialogs["PR_FRAME_SAVE_ERROR"] = {
+ text = "",
+ button1 = TEXT(OKAY),
+ OnAccept = function()
+ end,
+ timeout = 0,
+ hideOnEscape = 1
+}