Back to Home

ESO Lua File v101044

libraries/utility/zo_radiobuttongroup.lua

[◄ back to folders ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
ZO_RadioButtonGroup = ZO_InitializingObject:Subclass()
function ZO_RadioButtonGroup:Initialize(allowUnclick)
    self.m_buttons = {}
    self.m_enabled = true
    self.allowUnclick = allowUnclick
    self:SetLabelColors(ZO_SELECTED_TEXT, ZO_DISABLED_TEXT)
end
function ZO_RadioButtonGroup:SetLabelColors(enabledColor, disabledColor)
    self.labelColorEnabled = enabledColor
    self.labelColorDisabled = disabledColor
end
function ZO_RadioButtonGroup:SetButtonState(button, clickedButton, enabled)
    if enabled then
        if button == clickedButton then
            button:SetState(BSTATE_PRESSED, true)
        else
            button:SetState(BSTATE_NORMAL, false)
        end
        if button.label then
            button.label:SetColor(self.labelColorEnabled:UnpackRGB())
        end
    else
        if button == clickedButton then
            button:SetState(BSTATE_DISABLED_PRESSED, true)
        else
            button:SetState(BSTATE_DISABLED, true)
        end
        if button.label then
            button.label:SetColor(self.labelColorDisabled:UnpackRGB())
        end
    end
end
function ZO_RadioButtonGroup:HandleClick(control, buttonId, ignoreCallback)
    if not self.m_enabled then
        return
    end
    -- Can't click if already clicked, unless that's explicitly allowed
    if (self.m_clickedButton == control) and not self.allowUnclick then
        return
    end
    -- Can't click disabled/invalid buttons
    local buttonData = self.m_buttons[control]
    if not buttonData or not buttonData.isValidOption then
        return
    end
    if self.customClickHandler and self.customClickHandler(control, buttonId, ignoreCallback) then
        return
    end
    -- For now only the LMB will be allowed to click radio buttons.
    if buttonId == MOUSE_BUTTON_INDEX_LEFT then
        -- Set all buttons in the group to unpressed, and unlocked.
        -- If the button is disabled externally (maybe it isn't a valid option at this time)
        -- then set it to unpressed, but disabled.
        for k, v in pairs(self.m_buttons) do
            self:SetButtonState(k, nil, v.isValidOption)
        end
        local previousControl = self.m_clickedButton
        if self.m_clickedButton == control then
            self.m_clickedButton = nil
        else
            self.m_clickedButton = control
            -- Set the clicked button to pressed and lock it down (so that it stays pressed.)
            control:SetState(BSTATE_PRESSED, true)
        end
        if self.onSelectionChangedCallback and not ignoreCallback then
            self:onSelectionChangedCallback(self.m_clickedButton, previousControl)
        end
    end
    if buttonData.originalHandler then
        buttonData.originalHandler(control, buttonId)
    end
end
function ZO_RadioButtonGroup:Add(button)
    if button then
        if self.m_buttons[button] == nil then
            -- Remember the original handler so that its call can be forced.
            local originalHandler = button:GetHandler("OnClicked")
            self.m_buttons[button] = { originalHandler = originalHandler, isValidOption = true } -- newly added buttons always start as valid options for now.
            -- This throws away return values from the original function, which is most likely ok in the case of a click handler.
            local newHandler = function(control, buttonId, ignoreCallback)
                self:HandleClick(control, buttonId, ignoreCallback)
            end
            button:SetHandler("OnClicked", newHandler)
            if button.label then
                button.label:SetColor(self.labelColorEnabled:UnpackRGB())
            end
        end
    end
end
function ZO_RadioButtonGroup:Remove(button)
    local buttonData = button and self.m_buttons[button]
    if buttonData then
        button:SetHandler("OnClicked", buttonData.originalHandler)
        -- Restore the button to its correct state, as if it hadn't been added to the radio group
        -- Since "valid option" is set externally, just use that to figure out the current enabled state.
        self:SetButtonState(button, nil, buttonData.isValidOption)
        self.m_buttons[button] = nil
        if button == self.m_clickedButton then
            self.m_clickedButton = nil
        end
    end
end
-- This changes the enabled state of the entire radio group, but must still take into account
-- whether each button is a valid option...for example, enabling a radio group that has certain
-- invalid options must remember to keep those options disabled.
function ZO_RadioButtonGroup:SetEnabled(enabled)
    if enabled ~= self.m_enabled then
        self.m_enabled = enabled
        local clickedButton = self:GetClickedButton()
        for k, v in pairs(self.m_buttons) do
            local buttonEnabled = enabled and v.isValidOption
            self:SetButtonState(k, clickedButton, buttonEnabled)
        end
    end
end
-- Allow external control over whether individual buttons are valid options
-- within the group. Invalid options will force those buttons to appear disabled.
function ZO_RadioButtonGroup:SetButtonIsValidOption(button, isValidOption)
    local buttonData = self.m_buttons[button]
    if buttonData and (isValidOption ~= buttonData.isValidOption) then
        buttonData.isValidOption = isValidOption
        
        -- NOTE: This doesn't update the state of the clicked button, because that could
        -- potentially call a click handler that shouldn't be called at this time, or cause
        -- more data to need to be updated externally...it's a best practice to first figure
        -- out which buttons need to be validOptions, and then allow the clicked button to change.
        self:SetButtonState(button, self:GetClickedButton(), self.m_enabled and isValidOption)
    end
end
function ZO_RadioButtonGroup:Clear()
    for k, v in pairs(self.m_buttons) do
        -- Restore the button to its correct state, as if it hadn't been added to the radio group
        -- Since "valid option" is set externally, just use that to figure out the current enabled state.
        self:SetButtonState(k, nil, v.isValidOption)
        
        -- Reset handler, it's ok if this is nil, it means there was no original handler
        -- so there shouldn't be one now...
        k:SetHandler("OnClicked", v.originalHandler)
    end
    
    self.m_buttons = {}
    self.m_clickedButton = nil
end
function ZO_RadioButtonGroup:SetClickedButton(button, ignoreCallback)
    self:HandleClick(button, MOUSE_BUTTON_INDEX_LEFT, ignoreCallback)
end
function ZO_RadioButtonGroup:SetButtonClickState(button, isClicked, ignoreCallback)
    local wasButtonClicked = self.m_clickedButton == button
    if wasButtonClicked ~= isClicked then
        self:HandleClick(button, MOUSE_BUTTON_INDEX_LEFT, ignoreCallback)
    end
end
function ZO_RadioButtonGroup:GetClickedButton()
    return self.m_clickedButton
end
-- Just change the state of the button group to reflect the current state of the data;
-- this shouldn't actually call any click handlers.
function ZO_RadioButtonGroup:UpdateFromData(isPressedQueryFn)
    -- Find the button that's actually the clicked button from backing data
    self.m_clickedButton = nil
    for button, buttonData in pairs(self.m_buttons) do
        if isPressedQueryFn(button) then
            self.m_clickedButton = button
            break
        end
    end
    -- Update the state of all the buttons and reassign the currently clicked button
    local clickedButton = self.m_clickedButton
    local enabled = self.m_enabled
    for button, buttonData in pairs(self.m_buttons) do
        local buttonEnabled = enabled and buttonData.isValidOption
        self:SetButtonState(button, clickedButton, buttonEnabled)
    end
end
function ZO_RadioButtonGroup:SetSelectionChangedCallback(callback)
end
function ZO_RadioButtonGroup:IterateButtons()
    -- key: button, value: buttonData
    return pairs(self.m_buttons)
end
function ZO_RadioButtonGroup:SetCustomClickHandler(customClickHandler)
end