ESOUI SVN TaosGroupUltimate

[/] [trunk/] [TaosGroupUltimate/] [libs/] [LibAddonMenu-2.0/] [controls/] [dropdown.lua] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 Taonnor-14572
--[[dropdownData = {
2 Taonnor-14572
    type = "dropdown",
3 Taonnor-14572
    name = "My Dropdown", -- or string id or function returning a string
4 Taonnor-14572
    choices = {"table", "of", "choices"},
5 Taonnor-14572
    choicesValues = {"foo", 2, "three"}, -- if specified, these values will get passed to setFunc instead (optional)
6 Taonnor-14572
    getFunc = function() return db.var end,
7 Taonnor-14572
    setFunc = function(var) db.var = var doStuff() end,
8 Taonnor-14572
    tooltip = "Dropdown's tooltip text.", -- or string id or function returning a string (optional)
9 Taonnor-14572
    choicesTooltips = {"tooltip 1", "tooltip 2", "tooltip 3"}, -- or array of string ids or array of functions returning a string (optional)
10 Taonnor-14572
    sort = "name-up", --or "name-down", "numeric-up", "numeric-down", "value-up", "value-down", "numericvalue-up", "numericvalue-down" (optional) - if not provided, list will not be sorted
11 Taonnor-14572
    width = "full", --or "half" (optional)
12 Taonnor-14572
    scrollable = true, -- boolean or number, if set the dropdown will feature a scroll bar if there are a large amount of choices and limit the visible lines to the specified number or 10 if true is used (optional)
13 Taonnor-14572
    disabled = function() return db.someBooleanSetting end, --or boolean (optional)
14 Taonnor-14572
    warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional)
15 Taonnor-14572
    requiresReload = false, -- boolean, if set to true, the warning text will contain a notice that changes are only applied after an UI reload and any change to the value will make the "Apply Settings" button appear on the panel which will reload the UI when pressed (optional)
16 Taonnor-14572
    default = defaults.var, -- default value or function that returns the default value (optional)
17 Taonnor-14572
    reference = "MyAddonDropdown" -- unique global reference to control (optional)
18 Taonnor-14572
} ]]
19 Taonnor-14572
 
20 Taonnor-14572
 
21 Taonnor-14572
local widgetVersion = 17
22 Taonnor-14572
local LAM = LibStub("LibAddonMenu-2.0")
23 Taonnor-14572
if not LAM:RegisterWidget("dropdown", widgetVersion) then return end
24 Taonnor-14572
 
25 Taonnor-14572
local wm = WINDOW_MANAGER
26 Taonnor-14572
local SORT_BY_VALUE         = { ["value"] = {} }
27 Taonnor-14572
local SORT_BY_VALUE_NUMERIC = { ["value"] = { isNumeric = true } }
28 Taonnor-14572
local SORT_TYPES = {
29 Taonnor-14572
    name = ZO_SORT_BY_NAME,
30 Taonnor-14572
    numeric = ZO_SORT_BY_NAME_NUMERIC,
31 Taonnor-14572
    value = SORT_BY_VALUE,
32 Taonnor-14572
    numericvalue = SORT_BY_VALUE_NUMERIC,
33 Taonnor-14572
}
34 Taonnor-14572
local SORT_ORDERS = {
35 Taonnor-14572
    up = ZO_SORT_ORDER_UP,
36 Taonnor-14572
    down = ZO_SORT_ORDER_DOWN,
37 Taonnor-14572
}
38 Taonnor-14572
 
39 Taonnor-14572
local function UpdateDisabled(control)
40 Taonnor-14572
    local disable
41 Taonnor-14572
    if type(control.data.disabled) == "function" then
42 Taonnor-14572
        disable = control.data.disabled()
43 Taonnor-14572
    else
44 Taonnor-14572
        disable = control.data.disabled
45 Taonnor-14572
    end
46 Taonnor-14572
 
47 Taonnor-14572
    control.dropdown:SetEnabled(not disable)
48 Taonnor-14572
    if disable then
49 Taonnor-14572
        control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
50 Taonnor-14572
    else
51 Taonnor-14572
        control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
52 Taonnor-14572
    end
53 Taonnor-14572
end
54 Taonnor-14572
 
55 Taonnor-14572
local function UpdateValue(control, forceDefault, value)
56 Taonnor-14572
    if forceDefault then --if we are forcing defaults
57 Taonnor-14572
        value = LAM.util.GetDefaultValue(control.data.default)
58 Taonnor-14572
        control.data.setFunc(value)
59 Taonnor-14572
        control.dropdown:SetSelectedItem(control.choices[value])
60 Taonnor-14572
    elseif value then
61 Taonnor-14572
        control.data.setFunc(value)
62 Taonnor-14572
        --after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
63 Taonnor-14572
        LAM.util.RequestRefreshIfNeeded(control)
64 Taonnor-14572
    else
65 Taonnor-14572
        value = control.data.getFunc()
66 Taonnor-14572
        control.dropdown:SetSelectedItem(control.choices[value])
67 Taonnor-14572
    end
68 Taonnor-14572
end
69 Taonnor-14572
 
70 Taonnor-14572
local function DropdownCallback(control, choiceText, choice)
71 Taonnor-14572
    choice.control:UpdateValue(false, choice.value or choiceText)
72 Taonnor-14572
end
73 Taonnor-14572
 
74 Taonnor-14572
local function SetupTooltips(comboBox, choicesTooltips)
75 Taonnor-14572
    local function ShowTooltip(control)
76 Taonnor-14572
        InitializeTooltip(InformationTooltip, control, TOPLEFT, 0, 0, BOTTOMRIGHT)
77 Taonnor-14572
        SetTooltipText(InformationTooltip, LAM.util.GetStringFromValue(control.tooltip))
78 Taonnor-14572
        InformationTooltipTopLevel:BringWindowToTop()
79 Taonnor-14572
    end
80 Taonnor-14572
    local function HideTooltip(control)
81 Taonnor-14572
        ClearTooltip(InformationTooltip)
82 Taonnor-14572
    end
83 Taonnor-14572
 
84 Taonnor-14572
    -- allow for tooltips on the drop down entries
85 Taonnor-14572
    local originalShow = comboBox.ShowDropdownInternal
86 Taonnor-14572
    comboBox.ShowDropdownInternal = function(comboBox)
87 Taonnor-14572
        originalShow(comboBox)
88 Taonnor-14572
        local entries = ZO_Menu.items
89 Taonnor-14572
        for i = 1, #entries do
90 Taonnor-14572
            local entry = entries[i]
91 Taonnor-14572
            local control = entries[i].item
92 Taonnor-14572
            control.tooltip = choicesTooltips[i]
93 Taonnor-14572
            entry.onMouseEnter = control:GetHandler("OnMouseEnter")
94 Taonnor-14572
            entry.onMouseExit = control:GetHandler("OnMouseExit")
95 Taonnor-14572
            ZO_PreHookHandler(control, "OnMouseEnter", ShowTooltip)
96 Taonnor-14572
            ZO_PreHookHandler(control, "OnMouseExit", HideTooltip)
97 Taonnor-14572
        end
98 Taonnor-14572
    end
99 Taonnor-14572
 
100 Taonnor-14572
    local originalHide = comboBox.HideDropdownInternal
101 Taonnor-14572
    comboBox.HideDropdownInternal = function(self)
102 Taonnor-14572
        local entries = ZO_Menu.items
103 Taonnor-14572
        for i = 1, #entries do
104 Taonnor-14572
            local entry = entries[i]
105 Taonnor-14572
            local control = entries[i].item
106 Taonnor-14572
            control:SetHandler("OnMouseEnter", entry.onMouseEnter)
107 Taonnor-14572
            control:SetHandler("OnMouseExit", entry.onMouseExit)
108 Taonnor-14572
            control.tooltip = nil
109 Taonnor-14572
        end
110 Taonnor-14572
        originalHide(self)
111 Taonnor-14572
    end
112 Taonnor-14572
end
113 Taonnor-14572
 
114 Taonnor-14572
local function UpdateChoices(control, choices, choicesValues, choicesTooltips)
115 Taonnor-14572
    control.dropdown:ClearItems() --remove previous choices --(need to call :SetSelectedItem()?)
116 Taonnor-14572
    ZO_ClearTable(control.choices)
117 Taonnor-14572
 
118 Taonnor-14572
    --build new list of choices
119 Taonnor-14572
    local choices = choices or control.data.choices
120 Taonnor-14572
    local choicesValues = choicesValues or control.data.choicesValues
121 Taonnor-14572
    local choicesTooltips = choicesTooltips or control.data.choicesTooltips
122 Taonnor-14572
 
123 Taonnor-14572
    if choicesValues then
124 Taonnor-14572
        assert(#choices == #choicesValues, "choices and choicesValues need to have the same size")
125 Taonnor-14572
    end
126 Taonnor-14572
 
127 Taonnor-14572
    if choicesTooltips then
128 Taonnor-14572
        assert(#choices == #choicesTooltips, "choices and choicesTooltips need to have the same size")
129 Taonnor-14572
        SetupTooltips(control.dropdown, choicesTooltips)
130 Taonnor-14572
    end
131 Taonnor-14572
 
132 Taonnor-14572
    for i = 1, #choices do
133 Taonnor-14572
        local entry = control.dropdown:CreateItemEntry(choices[i], DropdownCallback)
134 Taonnor-14572
        entry.control = control
135 Taonnor-14572
        if choicesValues then
136 Taonnor-14572
            entry.value = choicesValues[i]
137 Taonnor-14572
        end
138 Taonnor-14572
        control.choices[entry.value or entry.name] = entry.name
139 Taonnor-14572
        control.dropdown:AddItem(entry, not control.data.sort and ZO_COMBOBOX_SUPRESS_UPDATE) --if sort type/order isn't specified, then don't sort
140 Taonnor-14572
    end
141 Taonnor-14572
end
142 Taonnor-14572
 
143 Taonnor-14572
local function GrabSortingInfo(sortInfo)
144 Taonnor-14572
    local t, i = {}, 1
145 Taonnor-14572
    for info in string.gmatch(sortInfo, "([^%-]+)") do
146 Taonnor-14572
        t[i] = info
147 Taonnor-14572
        i = i + 1
148 Taonnor-14572
    end
149 Taonnor-14572
 
150 Taonnor-14572
    return t
151 Taonnor-14572
end
152 Taonnor-14572
 
153 Taonnor-14572
local DEFAULT_VISIBLE_ROWS = 10
154 Taonnor-14572
local SCROLLABLE_ENTRY_TEMPLATE_HEIGHT = 25 -- same as in zo_combobox.lua
155 Taonnor-14572
local CONTENT_PADDING = 24
156 Taonnor-14572
local SCROLLBAR_PADDING = 16
157 Taonnor-14572
local PADDING = GetMenuPadding() / 2 -- half the amount looks closer to the regular dropdown
158 Taonnor-14572
local ScrollableDropdownHelper = ZO_Object:Subclass()
159 Taonnor-14572
 
160 Taonnor-14572
function ScrollableDropdownHelper:New(...)
161 Taonnor-14572
    local object = ZO_Object.New(self)
162 Taonnor-14572
    object:Initialize(...)
163 Taonnor-14572
    return object
164 Taonnor-14572
end
165 Taonnor-14572
 
166 Taonnor-14572
function ScrollableDropdownHelper:Initialize(parent, control, visibleRows)
167 Taonnor-14572
    local combobox = control.combobox
168 Taonnor-14572
    local dropdown = control.dropdown
169 Taonnor-14572
    self.parent = parent
170 Taonnor-14572
    self.control = control
171 Taonnor-14572
    self.combobox = combobox
172 Taonnor-14572
    self.dropdown = dropdown
173 Taonnor-14572
    self.visibleRows = visibleRows
174 Taonnor-14572
 
175 Taonnor-14572
    -- clear anchors so we can adjust the width dynamically
176 Taonnor-14572
    dropdown.m_dropdown:ClearAnchors()
177 Taonnor-14572
    dropdown.m_dropdown:SetAnchor(TOPLEFT, combobox, BOTTOMLEFT)
178 Taonnor-14572
 
179 Taonnor-14572
    -- handle dropdown or settingsmenu opening/closing
180 Taonnor-14572
    local function onShow() self:OnShow() end
181 Taonnor-14572
    local function onHide() self:OnHide() end
182 Taonnor-14572
    local function doHide() self:DoHide() end
183 Taonnor-14572
 
184 Taonnor-14572
    ZO_PreHook(dropdown, "ShowDropdownOnMouseUp", onShow)
185 Taonnor-14572
    ZO_PreHook(dropdown, "HideDropdownInternal", onHide)
186 Taonnor-14572
    combobox:SetHandler("OnEffectivelyHidden", onHide)
187 Taonnor-14572
    parent:SetHandler("OnEffectivelyHidden", doHide)
188 Taonnor-14572
 
189 Taonnor-14572
    -- dont fade entries near the edges
190 Taonnor-14572
    local scrollList = dropdown.m_scroll
191 Taonnor-14572
    scrollList.selectionTemplate = nil
192 Taonnor-14572
    scrollList.highlightTemplate = nil
193 Taonnor-14572
    ZO_ScrollList_EnableSelection(scrollList, "ZO_SelectionHighlight")
194 Taonnor-14572
    ZO_ScrollList_EnableHighlight(scrollList, "ZO_SelectionHighlight")
195 Taonnor-14572
    ZO_Scroll_SetUseFadeGradient(scrollList, false)
196 Taonnor-14572
 
197 Taonnor-14572
    -- adjust scroll content anchor to mimic menu padding
198 Taonnor-14572
    local scroll = dropdown.m_dropdown:GetNamedChild("Scroll")
199 Taonnor-14572
    local anchor1 = {scroll:GetAnchor(0)}
200 Taonnor-14572
    local anchor2 = {scroll:GetAnchor(1)}
201 Taonnor-14572
    scroll:ClearAnchors()
202 Taonnor-14572
    scroll:SetAnchor(anchor1[2], anchor1[3], anchor1[4], anchor1[5] + PADDING, anchor1[6] + PADDING)
203 Taonnor-14572
    scroll:SetAnchor(anchor2[2], anchor2[3], anchor2[4], anchor2[5] - PADDING, anchor2[6] - PADDING)
204 Taonnor-14572
    ZO_ScrollList_Commit(scrollList)
205 Taonnor-14572
 
206 Taonnor-14572
    -- adjust row setup to mimic the highlight padding
207 Taonnor-14572
    local dataType1 = ZO_ScrollList_GetDataTypeTable(dropdown.m_scroll, 1)
208 Taonnor-14572
    local dataType2 = ZO_ScrollList_GetDataTypeTable(dropdown.m_scroll, 2)
209 Taonnor-14572
    local oSetup = dataType1.setupCallback -- both types have the same setup function
210 Taonnor-14572
    local function SetupEntry(control, data, list)
211 Taonnor-14572
        oSetup(control, data, list)
212 Taonnor-14572
        control.m_label:SetAnchor(LEFT, nil, nil, 2)
213 Taonnor-14572
    end
214 Taonnor-14572
    dataType1.setupCallback = SetupEntry
215 Taonnor-14572
    dataType2.setupCallback = SetupEntry
216 Taonnor-14572
 
217 Taonnor-14572
    -- adjust dimensions based on entries
218 Taonnor-14572
    local scrollContent = scroll:GetNamedChild("Contents")
219 Taonnor-14572
    ZO_PreHook(dropdown, "AddMenuItems", function()
220 Taonnor-14572
        local width = PADDING * 2 + zo_max(self:GetMaxWidth(), combobox:GetWidth())
221 Taonnor-14572
        local numItems = #dropdown.m_sortedItems
222 Taonnor-14572
        local anchorOffset = 0
223 Taonnor-14572
        if(numItems > self.visibleRows) then
224 Taonnor-14572
            width = width + CONTENT_PADDING + SCROLLBAR_PADDING
225 Taonnor-14572
            anchorOffset = -SCROLLBAR_PADDING
226 Taonnor-14572
            numItems = self.visibleRows
227 Taonnor-14572
        end
228 Taonnor-14572
        scrollContent:SetAnchor(BOTTOMRIGHT, nil, nil, anchorOffset)
229 Taonnor-14572
        local height = PADDING * 2 + numItems * (SCROLLABLE_ENTRY_TEMPLATE_HEIGHT + dropdown.m_spacing) - dropdown.m_spacing
230 Taonnor-14572
        dropdown.m_dropdown:SetWidth(width)
231 Taonnor-14572
        dropdown.m_dropdown:SetHeight(height)
232 Taonnor-14572
    end)
233 Taonnor-14572
end
234 Taonnor-14572
 
235 Taonnor-14572
function ScrollableDropdownHelper:OnShow()
236 Taonnor-14572
    local dropdown = self.dropdown
237 Taonnor-14572
    if dropdown.m_lastParent ~= ZO_Menus then
238 Taonnor-14572
        dropdown.m_lastParent = dropdown.m_dropdown:GetParent()
239 Taonnor-14572
        dropdown.m_dropdown:SetParent(ZO_Menus)
240 Taonnor-14572
        ZO_Menus:BringWindowToTop()
241 Taonnor-14572
    end
242 Taonnor-14572
end
243 Taonnor-14572
 
244 Taonnor-14572
function ScrollableDropdownHelper:OnHide()
245 Taonnor-14572
    local dropdown = self.dropdown
246 Taonnor-14572
    if dropdown.m_lastParent then
247 Taonnor-14572
        dropdown.m_dropdown:SetParent(dropdown.m_lastParent)
248 Taonnor-14572
        dropdown.m_lastParent = nil
249 Taonnor-14572
    end
250 Taonnor-14572
end
251 Taonnor-14572
 
252 Taonnor-14572
function ScrollableDropdownHelper:DoHide()
253 Taonnor-14572
    local dropdown = self.dropdown
254 Taonnor-14572
    if dropdown:IsDropdownVisible() then
255 Taonnor-14572
        dropdown:HideDropdown()
256 Taonnor-14572
    end
257 Taonnor-14572
end
258 Taonnor-14572
 
259 Taonnor-14572
function ScrollableDropdownHelper:GetMaxWidth()
260 Taonnor-14572
    local dropdown = self.dropdown
261 Taonnor-14572
    local dataType = ZO_ScrollList_GetDataTypeTable(dropdown.m_scroll, 1)
262 Taonnor-14572
 
263 Taonnor-14572
    local dummy = dataType.pool:AcquireObject()
264 Taonnor-14572
    dataType.setupCallback(dummy, {
265 Taonnor-14572
        m_owner = dropdown,
266 Taonnor-14572
        name = "Dummy"
267 Taonnor-14572
    }, dropdown)
268 Taonnor-14572
 
269 Taonnor-14572
    local maxWidth = 0
270 Taonnor-14572
    local label = dummy.m_label
271 Taonnor-14572
    local entries = dropdown.m_sortedItems
272 Taonnor-14572
    local numItems = #entries
273 Taonnor-14572
    for index = 1, numItems do
274 Taonnor-14572
        label:SetText(entries[index].name)
275 Taonnor-14572
        local width = label:GetTextWidth()
276 Taonnor-14572
        if (width > maxWidth) then
277 Taonnor-14572
            maxWidth = width
278 Taonnor-14572
        end
279 Taonnor-14572
    end
280 Taonnor-14572
 
281 Taonnor-14572
    dataType.pool:ReleaseObject(dummy.key)
282 Taonnor-14572
    return maxWidth
283 Taonnor-14572
end
284 Taonnor-14572
 
285 Taonnor-14572
function LAMCreateControl.dropdown(parent, dropdownData, controlName)
286 Taonnor-14572
    local control = LAM.util.CreateLabelAndContainerControl(parent, dropdownData, controlName)
287 Taonnor-14572
    control.choices = {}
288 Taonnor-14572
 
289 Taonnor-14572
    local countControl = parent
290 Taonnor-14572
    local name = parent:GetName()
291 Taonnor-14572
    if not name or #name == 0 then
292 Taonnor-14572
        countControl = LAMCreateControl
293 Taonnor-14572
        name = "LAM"
294 Taonnor-14572
    end
295 Taonnor-14572
    local comboboxCount = (countControl.comboboxCount or 0) + 1
296 Taonnor-14572
    countControl.comboboxCount = comboboxCount
297 Taonnor-14572
    control.combobox = wm:CreateControlFromVirtual(zo_strjoin(nil, name, "Combobox", comboboxCount), control.container, dropdownData.scrollable and "ZO_ScrollableComboBox" or "ZO_ComboBox")
298 Taonnor-14572
 
299 Taonnor-14572
    local combobox = control.combobox
300 Taonnor-14572
    combobox:SetAnchor(TOPLEFT)
301 Taonnor-14572
    combobox:SetDimensions(control.container:GetDimensions())
302 Taonnor-14572
    combobox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
303 Taonnor-14572
    combobox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end)
304 Taonnor-14572
    control.dropdown = ZO_ComboBox_ObjectFromContainer(combobox)
305 Taonnor-14572
    local dropdown = control.dropdown
306 Taonnor-14572
    dropdown:SetSortsItems(false) -- need to sort ourselves in order to be able to sort by value
307 Taonnor-14572
 
308 Taonnor-14572
    if dropdownData.scrollable then
309 Taonnor-14572
        local visibleRows = type(dropdownData.scrollable) == "number" and dropdownData.scrollable or DEFAULT_VISIBLE_ROWS
310 Taonnor-14572
        control.scrollHelper = ScrollableDropdownHelper:New(parent, control, visibleRows)
311 Taonnor-14572
    end
312 Taonnor-14572
 
313 Taonnor-14572
    ZO_PreHook(dropdown, "UpdateItems", function(self)
314 Taonnor-14572
        assert(not self.m_sortsItems, "built-in dropdown sorting was reactivated, sorting is handled by LAM")
315 Taonnor-14572
        if control.m_sortOrder ~= nil and control.m_sortType then
316 Taonnor-14572
            local sortKey = next(control.m_sortType)
317 Taonnor-14572
            local sortFunc = function(item1, item2) return ZO_TableOrderingFunction(item1, item2, sortKey, control.m_sortType, control.m_sortOrder) end
318 Taonnor-14572
            table.sort(self.m_sortedItems, sortFunc)
319 Taonnor-14572
        end
320 Taonnor-14572
    end)
321 Taonnor-14572
 
322 Taonnor-14572
    if dropdownData.sort then
323 Taonnor-14572
        local sortInfo = GrabSortingInfo(dropdownData.sort)
324 Taonnor-14572
        control.m_sortType, control.m_sortOrder = SORT_TYPES[sortInfo[1]], SORT_ORDERS[sortInfo[2]]
325 Taonnor-14572
    elseif dropdownData.choicesValues then
326 Taonnor-14572
        control.m_sortType, control.m_sortOrder = ZO_SORT_ORDER_UP, SORT_BY_VALUE
327 Taonnor-14572
    end
328 Taonnor-14572
 
329 Taonnor-14572
    if dropdownData.warning ~= nil or dropdownData.requiresReload then
330 Taonnor-14572
        control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
331 Taonnor-14572
        control.warning:SetAnchor(RIGHT, combobox, LEFT, -5, 0)
332 Taonnor-14572
        control.UpdateWarning = LAM.util.UpdateWarning
333 Taonnor-14572
        control:UpdateWarning()
334 Taonnor-14572
    end
335 Taonnor-14572
 
336 Taonnor-14572
    control.UpdateChoices = UpdateChoices
337 Taonnor-14572
    control:UpdateChoices(dropdownData.choices, dropdownData.choicesValues)
338 Taonnor-14572
    control.UpdateValue = UpdateValue
339 Taonnor-14572
    control:UpdateValue()
340 Taonnor-14572
    if dropdownData.disabled ~= nil then
341 Taonnor-14572
        control.UpdateDisabled = UpdateDisabled
342 Taonnor-14572
        control:UpdateDisabled()
343 Taonnor-14572
    end
344 Taonnor-14572
 
345 Taonnor-14572
    LAM.util.RegisterForRefreshIfNeeded(control)
346 Taonnor-14572
    LAM.util.RegisterForReloadIfNeeded(control)
347 Taonnor-14572
 
348 Taonnor-14572
    return control
349 Taonnor-14572
end