Mercurial > wow > reaction
diff modules/ReAction_ConfigUI/ReAction_ConfigUI.lua @ 25:bf997ea151ca
yet another attempt to add missing files
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Fri, 07 Mar 2008 22:19:03 +0000 |
parents | |
children | 21bcaf8215ff |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/ReAction_ConfigUI/ReAction_ConfigUI.lua Fri Mar 07 22:19:03 2008 +0000 @@ -0,0 +1,608 @@ +--[[ + ReAction Configuration UI module + + This modules creates and manages ReAction configuration + elements, including: + + - waterfall config menu system + - bar dragging and resizing control overlays + - contextual menus + + Individual modules are responsible for populating these + configuration elements via the following functions: + + module:GetGlobalOptions( configModule ) + module:GetGlobalBarOptions( configModule ) + module:GetModuleOptions( configModule ) + module:GetBarConfigOptions( bar, configModule ) + module:GetBarMenuOptions( bar, configModule ) + + the ReAction_ConfigUI module is passed in as a parameter so that + option handlers can refresh the config UI. + +--]] + +-- local imports +local ReAction = ReAction +local L = ReAction.L +local _G = _G +local Waterfall = AceLibrary("Waterfall-1.0") +local Dewdrop = AceLibrary("Dewdrop-2.0") +local print = ReAction.print +local InCombatLockdown = InCombatLockdown +local BarModule = ReAction:GetModule("Bar") + +-- module declaration +local moduleID = "ConfigUI" +local module = ReAction:NewModule( moduleID, + "AceConsole-2.0", -- temp + "AceEvent-2.0" + -- mixins go here +) + +module.globalOptions = { + type = "group", + args = { + unlock = { + type = "toggle", + handler = module, + name = L["unlock"], + guiName = L["Unlock Bars"], + desc = L["Unlock bars for dragging and resizing with the mouse"], + get = function() return module.configMode end, + set = "SetConfigMode", + disabled = InCombatLockdown, + order = 1 + }, + config = { + type = "execute", + handler = module, + name = L["config"], + guiName = L["Configure..."], + desc = L["Open the configuration dialogue"], + func = "OpenConfig", + disabled = InCombatLockdown, + wfHidden = true, -- don't show this in the waterfall config + order = 2 + }, + } +} + +module.configOptions = { + type = "group", + args = { + global = { + type = "group", + name = L["Global Settings"], + desc = L["Global configuration settings"], + args = { }, + order = 1, + }, + module = { + type = "group", + name = L["Module Settings"], + desc = L["Configuration settings for each module"], + args = { }, + order = 2, + }, + bar = { + type = "group", + name = L["Bars"], + desc = L["Configuration settings for bars"], + args = { }, + order = 3, + }, + } +} + +-- module methods +function module:OnInitialize() + self.db = ReAction:AcquireDBNamespace(moduleID) + ReAction:RegisterDefaults(moduleID,"profile", + { + + } + ) + + -- temp: this will be moved to main ReAction.lua later in a more efficient AceConsole-less implementation + -- that can load the ConfigUI module on demand + -- NOTE: this inserts an 'about' command that we don't want + self:RegisterChatCommand( {L["/reaction"], L["/rxn"]}, self.globalOptions, "REACTION" ) +end + +function module:OnEnable() + self:RegisterEvent("PLAYER_REGEN_DISABLED") + Waterfall:Register("ReAction", + "aceOptions", self.configOptions, + "treeLevels", nil, -- infinite + "colorR", 0.8, + "colorG", 0.65, + "colorB", 0, + "defaultPane", "global" ) +end + +function module:OnDisable() + self:UnregisterEvent("PLAYER_REGEN_DISABLED") + self:SetConfigMode(false) + Waterfall:UnRegister("ReAction") +end + +function module:PLAYER_REGEN_DISABLED() + if self.configMode == true then + UIErrorsFrame:AddMessage(L["ReAction config mode disabled during combat."]) + self:SetConfigMode(false) + Waterfall:Close("ReAction") + end +end + +function module:SetConfigMode( mode ) + BarModule:CallMethodOnAllBars("ShowControls",mode) + ReAction:CallMethodOnAllModules("ApplyConfigMode",mode,BarModule.bars) + self.configMode = mode +end + +function module:ApplyConfigMode( mode, bars ) + if not(mode) then + -- close open dewdrop menu + local p = Dewdrop:GetOpenedParent() + if p then + for _, bar in pairs(bars) do + if bar then + if p == bar.controlFrame then + Dewdrop:Close() + end + end + end + end + end +end + +local function refreshWaterfall() + module:RefreshConfig() +end + +function module:RefreshOptions() + local opts = self.configOptions.args + + for _, m in ReAction:IterateModulesWithMethod("GetGlobalOptions") do + local o = m:GetGlobalOptions(self) + if o then + for k, v in pairs(o) do + opts.global.args[k] = v + end + end + end + + for _, m in ReAction:IterateModulesWithMethod("GetGlobalBarOptions") do + local o = m:GetGlobalBarOptions(self) + if o then + for k, v in pairs(o) do + opts.bar.args[k] = v + end + end + end + + for _, m in ReAction:IterateModulesWithMethod("GetModuleOptions") do + local o = m:GetModuleOptions(self) + if o then + for k, v in pairs(o) do + opts.module.args[k] = v + end + end + end + + local barOpts = opts.bar.args + for name, bar in pairs(BarModule.bars) do + if bar then + if barOpts[name] == nil then + barOpts[name] = { + type = "group", + name = name, + desc = name, + handler = bar, + args = { } + } + end + if bar.modConfigOpts == nil then + bar.modConfigOpts = { } + end + for _, m in ReAction:IterateModulesWithMethod("GetBarConfigOptions") do + local o = m:GetBarConfigOptions(bar,self) + if o then + for k, v in pairs(o) do + barOpts[name].args[k] = v + end + end + end + end + end + -- remove obsolete bar tables + for name, opt in pairs(barOpts) do + if opt.type == "group" and BarModule.bars[name] == nil then + barOpts[name] = nil + end + end +end + +function module:OpenConfig(bar) + self:RefreshOptions() + Dewdrop:Close() + Waterfall:Open("ReAction",bar and "bar."..bar:GetName()) +end + +function module:RefreshConfig() + self:RefreshOptions() + Waterfall:Refresh("ReAction") +end + +function module:ApplyToBar(bar) + if self.configMode then + bar:ShowControls(true) + end +end + +function module:RemoveFromBar(bar) + if bar.controlFrame then + bar.controlFrame:SetParent(UIParent) + bar.controlFrame:ClearAllPoints() + bar.controlFrame:Hide() + bar.controlFrame = nil + end +end + +function module:GetGlobalOptions() + return self.globalOptions.args +end + + + + + +-- +-- Bar config overlay +-- +-- import some of these for small OnUpdate performance boost +local Bar = BarModule.BarClass.prototype +local GetSize = Bar.GetSize +local GetButtonSize = Bar.GetButtonSize +local GetButtonGrid = Bar.GetButtonGrid +local SetSize = Bar.SetSize +local SetButtonSize = Bar.SetButtonSize +local SetButtonGrid = Bar.SetButtonGrid +local ApplyAnchor = Bar.ApplyAnchor +local floor = math.floor +local min = math.min +local format = string.format +local GameTooltip = GameTooltip + +local function StoreExtents(bar) + local f = bar.frame + local point, relativeTo, relativePoint, x, y = f:GetPoint(1) + relativeTo = relativeTo or f:GetParent() + local anchorTo + for name, b in pairs(BarModule.bars) do + if b then + if b:GetFrame() == relativeTo then + anchorTo = name + break + end + end + end + anchorTo = anchorTo or relativeTo:GetName() + local c = bar.config + c.anchor = point + c.anchorTo = anchorTo + c.relativePoint = relativePoint + c.x = x + c.y = y + c.width, c.height = f:GetWidth(), f:GetHeight() +end + +local function RecomputeButtonSize(bar) + local w, h = GetSize(bar) + local bw, bh = GetButtonSize(bar) + local r, c, s = GetButtonGrid(bar) + + local scaleW = (floor(w/c) - s) / bw + local scaleH = (floor(h/r) - s) / bh + local scale = min(scaleW, scaleH) + + SetButtonSize(bar, scale * bw, scale * bh, s) +end + +local function RecomputeButtonSpacing(bar) + local w, h = GetSize(bar) + local bw, bh = GetButtonSize(bar) + local r, c, s = GetButtonGrid(bar) + + SetButtonGrid(bar,r,c,min(floor(w/c) - bw, floor(h/r) - bh)) +end + +local function RecomputeGrid(bar) + local w, h = GetSize(bar) + local bw, bh = GetButtonSize(bar) + local r, c, s = GetButtonGrid(bar) + + SetButtonGrid(bar, floor(h/(bh+s)), floor(w/(bw+s)), s) +end + +local function ClampToButtons(bar) + local bw, bh = GetButtonSize(bar) + local r, c, s = GetButtonGrid(bar) + SetSize(bar, (bw+s)*c, (bh+s)*r ) +end + +local function HideGameTooltip() + GameTooltip:Hide() +end + +local function CreateControls(bar) + local f = bar.frame + + f:SetMovable(true) + f:SetResizable(true) + f:SetClampedToScreen(true) + + -- buttons on the bar should be direct children of the bar frame. + -- The control elements need to float on top of this, which we could + -- do with SetFrameLevel() or Raise(), but it's more reliable to do it + -- via frame nesting, hence good old foo's appearance here. + local foo = CreateFrame("Frame",nil,f) + foo:SetAllPoints() + + local control = CreateFrame("Button", nil, foo) + control:EnableMouse(true) + control:SetToplevel(true) + control:SetPoint("TOPLEFT", -4, 4) + control:SetPoint("BOTTOMRIGHT", 4, -4) + control:SetBackdrop({ + edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", + tile = true, + tileSize = 16, + edgeSize = 16, + insets = { left = 0, right = 0, top = 0, bottom = 0 }, + }) + + -- textures + local bgTex = control:CreateTexture(nil,"BACKGROUND") + bgTex:SetTexture(0.7,0.7,1.0,0.2) + bgTex:SetPoint("TOPLEFT",4,-4) + bgTex:SetPoint("BOTTOMRIGHT",-4,4) + local hTex = control:CreateTexture(nil,"HIGHLIGHT") + hTex:SetTexture(0.7,0.7,1.0,0.2) + hTex:SetPoint("TOPLEFT",4,-4) + hTex:SetPoint("BOTTOMRIGHT",-4,4) + hTex:SetBlendMode("ADD") + + -- label + local label = control:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") + label:SetAllPoints() + label:SetJustifyH("CENTER") + label:SetShadowColor(0,0,0,1) + label:SetShadowOffset(2,-2) + label:SetTextColor(1,1,1,1) + label:SetText(bar:GetName()) + label:Show() + bar.controlLabelString = label -- so that bar:SetName() can update it + + local StopResize = function() + f:StopMovingOrSizing() + f.isMoving = false + f:SetScript("OnUpdate",nil) + StoreExtents(bar) + ClampToButtons(bar) + ApplyAnchor(bar) + end + + -- edge drag handles + for _, point in pairs({"LEFT","TOP","RIGHT","BOTTOM"}) do + local edge = CreateFrame("Frame",nil,control) + edge:EnableMouse(true) + edge:SetWidth(8) + edge:SetHeight(8) + if point == "TOP" or point == "BOTTOM" then + edge:SetPoint(point.."LEFT") + edge:SetPoint(point.."RIGHT") + else + edge:SetPoint("TOP"..point) + edge:SetPoint("BOTTOM"..point) + end + local tex = edge:CreateTexture(nil,"HIGHLIGHT") + tex:SetTexture(1.0,0.82,0,0.7) + tex:SetBlendMode("ADD") + tex:SetAllPoints() + edge:RegisterForDrag("LeftButton") + edge:SetScript("OnMouseDown", + function() + local bw, bh = GetButtonSize(bar) + local r, c, s = GetButtonGrid(bar) + f:SetMinResize( bw+s+1, bh+s+1 ) + f:StartSizing(point) + f:SetScript("OnUpdate", + function() + RecomputeGrid(bar) + bar:RefreshLayout() + end + ) + end + ) + edge:SetScript("OnMouseUp", StopResize) + edge:SetScript("OnEnter", + function() + GameTooltip:SetOwner(f, "ANCHOR_"..point) + GameTooltip:AddLine(L["Drag to add/remove buttons"]) + GameTooltip:Show() + end + ) + edge:SetScript("OnLeave", HideGameTooltip) + edge:Show() + end + + -- corner drag handles, again nested in an anonymous frame so that they are on top + local foo2 = CreateFrame("Frame",nil,control) + foo2:SetAllPoints(true) + for _, point in pairs({"BOTTOMLEFT","TOPLEFT","BOTTOMRIGHT","TOPRIGHT"}) do + local corner = CreateFrame("Frame",nil,foo2) + corner:EnableMouse(true) + corner:SetWidth(12) + corner:SetHeight(12) + corner:SetPoint(point) + local tex = corner:CreateTexture(nil,"HIGHLIGHT") + tex:SetTexture(1.0,0.82,0,0.7) + tex:SetBlendMode("ADD") + tex:SetAllPoints() + corner:RegisterForDrag("LeftButton","RightButton") + local updateTooltip = function() + local size, size2 = bar:GetButtonSize() + local rows, cols, spacing = bar:GetButtonGrid() + size = (size == size2) and tostring(size) or format("%dx%d",size,size2) + GameTooltipTextRight4:SetText(size) + GameTooltipTextRight5:SetText(tostring(spacing)) + end + corner:SetScript("OnMouseDown", + function(_,btn) + local bw, bh = GetButtonSize(bar) + local r, c, s = GetButtonGrid(bar) + if btn == "LeftButton" then -- button resize + f:SetMinResize( (s+12)*c+1, (s+12)*r+1 ) + f:SetScript("OnUpdate", + function() + RecomputeButtonSize(bar) + bar:RefreshLayout() + updateTooltip() + end + ) + elseif btn == "RightButton" then -- spacing resize + f:SetMinResize( bw*c, bh*r ) + f:SetScript("OnUpdate", + function() + RecomputeButtonSpacing(bar) + bar:RefreshLayout() + updateTooltip() + end + ) + end + f:StartSizing(point) + end + ) + corner:SetScript("OnMouseUp",StopResize) + corner:SetScript("OnEnter", + function() + GameTooltip:SetOwner(f, "ANCHOR_"..point) + GameTooltip:AddLine(L["Drag to resize buttons"]) + GameTooltip:AddLine(L["Right-click-drag"]) + GameTooltip:AddLine(L["to change spacing"]) + local size, size2 = bar:GetButtonSize() + local rows, cols, spacing = bar:GetButtonGrid() + size = (size == size2) and tostring(size) or format("%dx%d",size,size2) + GameTooltip:AddDoubleLine(L["Size:"], size) + GameTooltip:AddDoubleLine(L["Spacing:"], tostring(spacing)) + GameTooltip:Show() + end + ) + corner:SetScript("OnLeave", + function() + GameTooltip:Hide() + f:SetScript("OnUpdate",nil) + end + ) + + end + + control:RegisterForDrag("LeftButton") + control:RegisterForClicks("RightButtonDown") + + control:SetScript("OnDragStart", + function() + f:StartMoving() + f.isMoving = true + -- TODO: snap indicator update install + end + ) + + control:SetScript("OnDragStop", + function() + f:StopMovingOrSizing() + f.isMoving = false + f:SetScript("OnUpdate",nil) + -- TODO: snap frame here + StoreExtents(bar) + end + ) + + control:SetScript("OnEnter", + function() + -- add bar type and status information to name + local name = bar.name + for _, m in ReAction:IterateModulesWithMethod("GetBarNameModifier") do + local suffix = m:GetBarNameModifier(bar) + if suffix then + name = format("%s %s",name,suffix) + end + end + + GameTooltip:SetOwner(f, "ANCHOR_TOPRIGHT") + GameTooltip:AddLine(name) + GameTooltip:AddLine(L["Drag to move"]) + --GameTooltip:AddLine(L["Shift-drag for sticky mode"]) + GameTooltip:AddLine(L["Right-click for options"]) + GameTooltip:Show() + end + ) + + control:SetScript("OnLeave", HideGameTooltip) + + control:SetScript("OnClick", + function() + bar:ShowMenu() + end + ) + + return control +end + +function Bar:ShowControls(show) + if show then + if not self.controlFrame then + self.controlFrame = CreateControls(self) + end + self.controlFrame:Show() + elseif self.controlFrame then + self.controlFrame:Hide() + end +end + +function Bar:ShowMenu() + if not self.menuOpts then + self.menuOpts = { + type = "group", + args = { + openConfig = { + type = "execute", + name = L["Configure..."], + desc = L["Open the configuration dialogue for this bar"], + func = function() module:OpenConfig(self) end, + disabled = InCombatLockdown, + order = 1 + } + } + } + end + if self.modMenuOpts == nil then + self.modMenuOpts = { } + end + for _, m in ReAction:IterateModulesWithMethod("GetBarMenuOptions") do + for k, v in pairs(m:GetBarMenuOptions(self, module)) do + self.menuOpts.args[k] = v + end + end + Dewdrop:Open(self.controlFrame, "children", self.menuOpts, "cursorX", true, "cursorY", true) +end + +local Bar_SuperSetName = Bar.SetName +function Bar:SetName(name) + Bar_SuperSetName(self,name) + if self.controlLabelString then + self.controlLabelString:SetText(self.name) + end +end