Skip to content

Commit 834cfeb

Browse files
committed
Implement an API to pick different widget styles
The public API is extended to take a widget style parameter anywhere a widget type is being supplied. If its not specified, classic style is assumed. The style parameter is a string for future expandability, currently defined as ACEGUI_STYLE_CLASSIC ("classic") for the default style shipping with AceGUI-3.0 Additional styles have to be registered, and can optionally take a parent style, which causes widgets not present in the requested style to be looked up from the parent instead. This enables partial style overrides. API Changes: AceGUI:RegisterStyle(style, parentStyle) AceGUI:Create(type, style) AceGUI:RegisterWidgetType(Name, Constructor, Version, Style) AceGUI:GetWidgetVersion(type, style) AceGUI:GetNextWidgetNum(type, style) AceGUI:GetWidgetCount(type, style)
1 parent fa50a0f commit 834cfeb

File tree

2 files changed

+120
-36
lines changed

2 files changed

+120
-36
lines changed

.luacheckrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ globals = {
2323
"CloseSpecialWindows",
2424
"ColorPickerFrame",
2525
"SlashCmdList", "hash_SlashCmdList",
26+
27+
"ACEGUI_STYLE_CLASSIC",
2628
}
2729

2830
read_globals = {

AceGUI-3.0/AceGUI-3.0.lua

Lines changed: 118 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
-- @class file
2626
-- @name AceGUI-3.0
2727
-- @release $Id$
28-
local ACEGUI_MAJOR, ACEGUI_MINOR = "AceGUI-3.0", 41
28+
local ACEGUI_MAJOR, ACEGUI_MINOR = "AceGUI-3.0", 50
2929
local AceGUI, oldminor = LibStub:NewLibrary(ACEGUI_MAJOR, ACEGUI_MINOR)
3030

3131
if not AceGUI then return end -- No upgrade needed
@@ -40,17 +40,35 @@ local math_max, math_min, math_ceil = math.max, math.min, math.ceil
4040
-- WoW APIs
4141
local UIParent = UIParent
4242

43+
ACEGUI_STYLE_CLASSIC = "classic"
44+
4345
AceGUI.WidgetRegistry = AceGUI.WidgetRegistry or {}
4446
AceGUI.LayoutRegistry = AceGUI.LayoutRegistry or {}
4547
AceGUI.WidgetBase = AceGUI.WidgetBase or {}
4648
AceGUI.WidgetContainerBase = AceGUI.WidgetContainerBase or {}
4749
AceGUI.WidgetVersions = AceGUI.WidgetVersions or {}
50+
AceGUI.WidgetStyles = AceGUI.WidgetStyles or {}
4851
AceGUI.tooltip = AceGUI.tooltip or CreateFrame("GameTooltip", "AceGUITooltip", UIParent, "GameTooltipTemplate")
52+
AceGUI.counts = AceGUI.counts or {}
53+
54+
-- migrate widget registry to per-style layout
55+
if oldminor and oldminor < 50 then
56+
local Registry = AceGUI.WidgetRegistry
57+
local Versions = AceGUI.WidgetVersions
58+
59+
AceGUI.WidgetRegistry = { [ACEGUI_STYLE_CLASSIC] = Registry }
60+
AceGUI.WidgetVersions = { [ACEGUI_STYLE_CLASSIC] = Versions }
61+
62+
-- migrate widget counts
63+
local counts = AceGUI.counts
64+
AceGUI.counts = { [ACEGUI_STYLE_CLASSIC] = counts }
65+
end
4966

5067
-- local upvalues
5168
local WidgetRegistry = AceGUI.WidgetRegistry
5269
local LayoutRegistry = AceGUI.LayoutRegistry
5370
local WidgetVersions = AceGUI.WidgetVersions
71+
local WidgetStyles = AceGUI.WidgetStyles
5472

5573
--[[
5674
xpcall safecall implementation
@@ -88,38 +106,42 @@ do
88106
AceGUI.objPools = AceGUI.objPools or {}
89107
local objPools = AceGUI.objPools
90108
--Returns a new instance, if none are available either returns a new table or calls the given contructor
91-
function newWidget(widgetType)
92-
if not WidgetRegistry[widgetType] then
109+
function newWidget(widgetType, style)
110+
if not WidgetRegistry[style] or not WidgetRegistry[style][widgetType] then
93111
error("Attempt to instantiate unknown widget type", 2)
94112
end
95113

96-
if not objPools[widgetType] then
97-
objPools[widgetType] = {}
114+
local poolKey = widgetType..style
115+
if not objPools[poolKey] then
116+
objPools[poolKey] = {}
98117
end
99118

100-
local newObj = next(objPools[widgetType])
119+
local newObj = next(objPools[poolKey])
101120
if not newObj then
102-
newObj = WidgetRegistry[widgetType]()
103-
newObj.AceGUIWidgetVersion = WidgetVersions[widgetType]
121+
newObj = WidgetRegistry[style][widgetType]()
122+
newObj.AceGUIWidgetVersion = WidgetVersions[style][widgetType]
123+
-- save the style for future recycling
124+
newObj.AceGUIWidgetStyle = style
104125
else
105-
objPools[widgetType][newObj] = nil
126+
objPools[poolKey][newObj] = nil
106127
-- if the widget is older then the latest, don't even try to reuse it
107128
-- just forget about it, and grab a new one.
108-
if not newObj.AceGUIWidgetVersion or newObj.AceGUIWidgetVersion < WidgetVersions[widgetType] then
109-
return newWidget(widgetType)
129+
if not newObj.AceGUIWidgetVersion or newObj.AceGUIWidgetVersion < WidgetVersions[style][widgetType] then
130+
return newWidget(widgetType, style)
110131
end
111132
end
112133
return newObj
113134
end
114135
-- Releases an instance to the Pool
115-
function delWidget(obj,widgetType)
116-
if not objPools[widgetType] then
117-
objPools[widgetType] = {}
136+
function delWidget(obj,widgetType,style)
137+
local poolKey = widgetType..style
138+
if not objPools[poolKey] then
139+
objPools[poolKey] = {}
118140
end
119-
if objPools[widgetType][obj] then
141+
if objPools[poolKey][obj] then
120142
error("Attempt to Release Widget that is already released", 2)
121143
end
122-
objPools[widgetType][obj] = true
144+
objPools[poolKey][obj] = true
123145
end
124146
end
125147

@@ -128,16 +150,52 @@ end
128150
-- API Functions --
129151
-------------------
130152

153+
--- Register a new widget style with AceGUI
154+
-- @param style The name of the style
155+
-- @param parentStyle The parent style, if any. Widgets from this style will be used if the selected style does not have one.
156+
function AceGUI:RegisterStyle(style, parentStyle)
157+
if type(style) ~= "string" then
158+
error("Style identifiers must be strings")
159+
end
160+
161+
if parentStyle and not WidgetStyles[tostring(parentStyle):lower()] then
162+
error("Parent Style is not defined")
163+
end
164+
165+
local widgetStyle = style:lower()
166+
WidgetStyles[widgetStyle] = { Parent = parentStyle }
167+
168+
WidgetRegistry[widgetStyle] = WidgetRegistry[widgetStyle] or {}
169+
WidgetVersions[widgetStyle] = WidgetVersions[widgetStyle] or {}
170+
AceGUI.counts[widgetStyle] = AceGUI.counts[widgetStyle] or {}
171+
end
172+
131173
-- Gets a widget Object
132174

133175
--- Create a new Widget of the given type.
134176
-- This function will instantiate a new widget (or use one from the widget pool), and call the
135177
-- OnAcquire function on it, before returning.
136178
-- @param type The type of the widget.
179+
-- @param style The widget style to use. String.
137180
-- @return The newly created widget.
138-
function AceGUI:Create(widgetType)
139-
if WidgetRegistry[widgetType] then
140-
local widget = newWidget(widgetType)
181+
function AceGUI:Create(widgetType, style)
182+
local widgetStyle
183+
184+
-- style selection
185+
if type(style) == "string" then
186+
-- string-type styles specify a style directly
187+
widgetStyle = style:lower()
188+
189+
if not WidgetStyles[widgetStyle] then
190+
error(("Requested style %s is not registered"):format(style))
191+
end
192+
else
193+
-- fallback to classic style (default)
194+
widgetStyle = ACEGUI_STYLE_CLASSIC
195+
end
196+
197+
if WidgetRegistry[widgetStyle] and WidgetRegistry[widgetStyle][widgetType] then
198+
local widget = newWidget(widgetType, widgetStyle)
141199

142200
if rawget(widget, "Acquire") then
143201
widget.OnAcquire = widget.Acquire
@@ -161,6 +219,11 @@ function AceGUI:Create(widgetType)
161219
safecall(widget.SetLayout, widget, "List")
162220
safecall(widget.ResumeLayout, widget)
163221
return widget
222+
else
223+
-- try to get a widget from the parent style instead
224+
if WidgetStyles[widgetStyle] and WidgetStyles[widgetStyle].Parent then
225+
return AceGUI:Create(widgetType, WidgetStyles[widgetStyle].Parent)
226+
end
164227
end
165228
end
166229

@@ -203,7 +266,7 @@ function AceGUI:Release(widget)
203266
widget.content.height = nil
204267
end
205268
widget.isQueuedForRelease = nil
206-
delWidget(widget, widget.type)
269+
delWidget(widget, widget.type, widget.AceGUIWidgetStyle or ACEGUI_STYLE_CLASSIC)
207270
end
208271

209272
--- Check if a widget is currently in the process of being released
@@ -546,15 +609,30 @@ end
546609
-- @param Name The name of the widget
547610
-- @param Constructor The widget constructor function
548611
-- @param Version The version of the widget
549-
function AceGUI:RegisterWidgetType(Name, Constructor, Version)
612+
function AceGUI:RegisterWidgetType(Name, Constructor, Version, Style)
550613
assert(type(Constructor) == "function")
551614
assert(type(Version) == "number")
615+
assert(Style == nil or type(Style) == "string")
616+
617+
local widgetStyle = Style and Style:lower() or ACEGUI_STYLE_CLASSIC
618+
619+
if not WidgetStyles[widgetStyle] then
620+
error(("Registering widget for unknown style: %s"):format(widgetStyle))
621+
end
552622

553-
local oldVersion = WidgetVersions[Name]
623+
if not WidgetRegistry[widgetStyle] then
624+
WidgetRegistry[widgetStyle] = {}
625+
end
626+
627+
if not WidgetVersions[widgetStyle] then
628+
WidgetVersions[widgetStyle] = {}
629+
end
630+
631+
local oldVersion = WidgetVersions[widgetStyle][Name]
554632
if oldVersion and oldVersion >= Version then return end
555633

556-
WidgetVersions[Name] = Version
557-
WidgetRegistry[Name] = Constructor
634+
WidgetVersions[widgetStyle][Name] = Version
635+
WidgetRegistry[widgetStyle][Name] = Constructor
558636
end
559637

560638
--- Registers a Layout Function
@@ -577,31 +655,35 @@ function AceGUI:GetLayout(Name)
577655
return LayoutRegistry[Name]
578656
end
579657

580-
AceGUI.counts = AceGUI.counts or {}
581-
582658
--- A type-based counter to count the number of widgets created.
583659
-- This is used by widgets that require a named frame, e.g. when a Blizzard
584660
-- Template requires it.
585-
-- @param type The widget type
586-
function AceGUI:GetNextWidgetNum(widgetType)
587-
if not self.counts[widgetType] then
588-
self.counts[widgetType] = 0
661+
-- @param widgetType The widget type
662+
-- @param widgetStyle The widget style
663+
function AceGUI:GetNextWidgetNum(widgetType, widgetStyle)
664+
local style = widgetStyle and widgetStyle:lower() or ACEGUI_STYLE_CLASSIC
665+
if not self.counts[style] then
666+
self.counts[style] = {}
589667
end
590-
self.counts[widgetType] = self.counts[widgetType] + 1
591-
return self.counts[widgetType]
668+
self.counts[style][widgetType] = (self.counts[style][widgetType] or 0) + 1
669+
return self.counts[style][widgetType]
592670
end
593671

594672
--- Return the number of created widgets for this type.
595673
-- In contrast to GetNextWidgetNum, the number is not incremented.
596674
-- @param widgetType The widget type
597-
function AceGUI:GetWidgetCount(widgetType)
598-
return self.counts[widgetType] or 0
675+
-- @param widgetStyle The widget style
676+
function AceGUI:GetWidgetCount(widgetType, widgetStyle)
677+
local style = widgetStyle and widgetStyle:lower() or ACEGUI_STYLE_CLASSIC
678+
return self.counts[style] and self.counts[style][widgetType] or 0
599679
end
600680

601681
--- Return the version of the currently registered widget type.
602682
-- @param widgetType The widget type
603-
function AceGUI:GetWidgetVersion(widgetType)
604-
return WidgetVersions[widgetType]
683+
-- @param widgetStyle The widget style
684+
function AceGUI:GetWidgetVersion(widgetType, widgetStyle)
685+
local style = widgetStyle and widgetStyle:lower() or ACEGUI_STYLE_CLASSIC
686+
return WidgetVersions[style] and WidgetVersions[style][widgetType] or nil
605687
end
606688

607689
-------------

0 commit comments

Comments
 (0)