Mercurial > wow > reaction
diff classes/Bar.lua @ 122:a2d2f23137c8
- Rearranged and consolidated some files in modules directory
- Added 'classes' directory, moved Bar and Overlay there
- Added Button, ActionButton, and GridProxy classes, not in use yet
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Mon, 23 Feb 2009 18:56:57 +0000 |
parents | |
children | 943eed2c7def |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/classes/Bar.lua Mon Feb 23 18:56:57 2009 +0000 @@ -0,0 +1,259 @@ +local ReAction = ReAction +local L = ReAction.L +local _G = _G +local CreateFrame = CreateFrame +local floor = math.floor +local fmod = math.fmod +local format = string.format + +ReAction:UpdateRevision("$Revision$") + +local Bar = { } +local proto = { __index = Bar } +local weak = { __mode = "k" } + +ReAction.Bar = Bar -- export to ReAction + +function Bar:New( name, config ) + if type(config) ~= "table" then + error("ReAction.Bar: config table required") + end + + -- create new self + self = setmetatable( + { + config = config, + name = name, + buttons = setmetatable( { }, weak ), + width = config.width or 480, + height = config.height or 40 + }, + proto ) + + -- The frame type is 'Button' in order to have an OnClick handler. However, the frame itself is + -- not mouse-clickable by the user. + local parent = config.parent and (ReAction:GetBar(config.parent) or _G[config.parent]) or UIParent + local f = CreateFrame("Button", name and format("ReAction-%s",name), parent, + "SecureHandlerStateTemplate, SecureHandlerClickTemplate") + f:SetFrameStrata("MEDIUM") + f:SetWidth(self.width) + f:SetWidth(self.height) + f:SetAlpha(config.alpha or 1.0) + f:Show() + f:EnableMouse(false) + f:SetClampedToScreen(true) + + f:SetAttribute("_onstate-showgrid", + -- function(self,stateid,newstate) + [[ + control:ChildUpdate(stateid,newstate) + control:CallMethod("UpdateShowGrid") + ]]) + f.UpdateShowGrid = function(frame) + for button in self:IterateButtons() do + button:UpdateShowGrid() + end + end + ReAction.gridProxy:AddFrame(f) + + -- Override the default frame accessor to provide strict read-only access + function self:GetFrame() + return f + end + + self:ApplyAnchor() + ReAction.RegisterCallback(self, "OnConfigModeChanged") + + return self +end + +function Bar:Destroy() + local f = self:GetFrame() + f:UnregisterAllEvents() + ReAction.UnregisterAllCallbacks(self) + ReAction.gridProxy:RemoveFrame(f) + f:Hide() + f:SetParent(UIParent) + f:ClearAllPoints() +end + +function Bar:OnConfigModeChanged(event, mode) + self:ShowControls(mode) -- Bar:ShowControls() defined in Overlay.lua +end + +function Bar:ApplyAnchor() + local f = self:GetFrame() + local c = self.config + local p = c.point + + f:SetWidth(c.width) + f:SetHeight(c.height) + f:ClearAllPoints() + + if p then + local a = f:GetParent() + if c.anchor then + local bar = ReAction:GetBar(c.anchor) + if bar then + a = bar:GetFrame() + else + a = _G[c.anchor] + end + end + local fr = a or f:GetParent() + f:SetPoint(p, a or f:GetParent(), c.relpoint, c.x or 0, c.y or 0) + else + f:SetPoint("CENTER") + end +end + +function Bar:SetAnchor(point, frame, relativePoint, x, y) + local c = self.config + c.point = point or c.point + c.anchor = frame or c.anchor + c.relpoint = relativePoint or c.relpoint + c.x = x or c.x + c.y = y or c.y + self:ApplyAnchor() + ReAction:RefreshBar(self) +end + +function Bar:GetAnchor() + local c = self.config + return (c.point or "CENTER"), + (c.anchor or self:GetFrame():GetParent():GetName()), + (c.relpoint or c.point or "CENTER"), + (c.x or 0), + (c.y or 0) +end + +function Bar:GetSize() + local f = self:GetFrame() + return f:GetWidth(), f:GetHeight() +end + +function Bar:SetSize(w,h) + local f = self:GetFrame() + self.config.width = w + self.config.height = h + f:SetWidth(w) + f:SetHeight(h) +end + +function Bar:GetButtonSize() + local w = self.config.btnWidth or 32 + local h = self.config.btnHeight or 32 + -- TODO: get from modules? + return w,h +end + +function Bar:SetButtonSize(w,h) + if w > 0 and h > 0 then + self.config.btnWidth = w + self.config.btnHeight = h + end + ReAction:RefreshBar(self) +end + +function Bar:GetButtonGrid() + local cfg = self.config + local r = cfg.btnRows or 1 + local c = cfg.btnColumns or 1 + local s = cfg.spacing or 4 + return r,c,s +end + +function Bar:GetNumButtons() + local r,c = self:GetButtonGrid() + return r*c +end + +function Bar:SetButtonGrid(r,c,s) + if r > 0 and c > 0 and s > 0 then + local cfg = self.config + cfg.btnRows = r + cfg.btnColumns = c + cfg.spacing = s + end + ReAction:RefreshBar(self) +end + +function Bar:ClipNButtons( n ) + local cfg = self.config + local r = cfg.btnRows or 1 + local c = cfg.btnColumns or 1 + + cfg.btnRows = ceil(n/c) + cfg.btnColumns = min(n,c) +end + +function Bar:GetName() + return self.name +end + +function Bar:GetFrame() + -- this method is included for documentation purposes. It is overridden + -- for each object in the :New() method. + error("Invalid Bar object: used without initialization") +end + +-- only ReAction:RenameBar() should call this function. Calling from any other +-- context will desync the bar list in the ReAction class. +function Bar:SetName(name) + self.name = name + self:SetLabel(self.name) -- Bar:SetLabel() defined in Overlay.lua +end + +function Bar:GetAlpha() + return self.config.alpha or 1.0 +end + +function Bar:SetAlpha(value) + self.config.alpha = value + self:GetFrame():SetAlpha(value or 1.0) + ReAction:RefreshBar(self) +end + +function Bar:AddButton(idx, button) + local f = self:GetFrame() + + -- store in a weak reverse-index array + self.buttons[button] = idx + + -- Store a properly wrapped reference to the child frame as an attribute + -- (accessible via "frameref-btn#") + f:SetFrameRef(format("btn%d",idx), button:GetFrame()) +end + +function Bar:RemoveButton(button) + local idx = self.buttons[button] + if idx then + self:GetFrame():SetAttribute(format("frameref-btn%d",idx),nil) + self.buttons[button] = nil + end +end + +-- iterator returns button, idx and does NOT iterate in index order +function Bar:IterateButtons() + return pairs(self.buttons) +end + +function Bar:PlaceButton(button, baseW, baseH) + local idx = self.buttons[button] + if idx then + local r, c, s = self:GetButtonGrid() + local bh, bw = self:GetButtonSize() + local row, col = floor((idx-1)/c), fmod((idx-1),c) -- zero-based + local x, y = col*bw + (col+0.5)*s, -(row*bh + (row+0.5)*s) + local scale = bw/baseW + local b = button:GetFrame() + + b:ClearAllPoints() + b:SetPoint("TOPLEFT",x/scale,y/scale) + b:SetScale(scale) + end +end + +function Bar:SkinButton() + -- does nothing by default +end \ No newline at end of file