You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bastion/libs/StdUi/widgets/Checkbox.lua

288 lines
6.7 KiB

--- @type StdUi
local StdUi = LibStub and LibStub('StdUi', true);
if not StdUi then
return
end
local module, version = 'Checkbox', 5;
if not StdUi:UpgradeNeeded(module, version) then
return
end
----------------------------------------------------
--- Checkbox
----------------------------------------------------
local CheckboxMethods = {
--- Set checkbox state
---
--- @param flag boolean
--- @param internal boolean - indicates to not run OnValueChanged
SetChecked = function(self, flag, internal)
self.isChecked = flag;
if not internal and self.OnValueChanged then
self:OnValueChanged(flag, self.value);
end
if not flag then
self.checkedTexture:Hide();
self.disabledCheckedTexture:Hide();
return
end
if self.isDisabled then
self.checkedTexture:Hide();
self.disabledCheckedTexture:Show();
else
self.checkedTexture:Show();
self.disabledCheckedTexture:Hide();
end
end,
GetChecked = function(self)
return self.isChecked;
end,
SetText = function(self, t)
self.text:SetText(t);
end,
SetValue = function(self, value)
self.value = value;
end,
GetValue = function(self)
if self:GetChecked() then
return self.value;
else
return nil;
end
end,
Disable = function(self)
self.isDisabled = true;
self:SetChecked(self.isChecked);
end,
Enable = function(self)
self.isDisabled = false;
self:SetChecked(self.isChecked);
end,
AutoWidth = function(self)
self:SetWidth(self.target:GetWidth() + 15 + self.text:GetWidth());
end
};
local CheckboxEvents = {
OnClick = function(self)
if not self.isDisabled then
self:SetChecked(not self:GetChecked());
end
end
}
---@return CheckButton
function StdUi:Checkbox(parent, text, width, height)
local checkbox = CreateFrame('Button', nil, parent);
checkbox.stdUi = self;
checkbox:EnableMouse(true);
self:SetObjSize(checkbox, width, height or 20);
self:InitWidget(checkbox);
checkbox.target = self:Panel(checkbox, 16, 16);
checkbox.target.stdUi = self;
checkbox.target:SetPoint('LEFT', 0, 0);
checkbox.value = true;
checkbox.isChecked = false;
checkbox.text = self:Label(checkbox, text);
checkbox.text:SetPoint('LEFT', checkbox.target, 'RIGHT', 5, 0);
checkbox.text:SetPoint('RIGHT', checkbox, 'RIGHT', -5, 0);
checkbox.target.text = checkbox.text; -- reference for disabled
checkbox.checkedTexture = self:Texture(checkbox.target, nil, nil, [[Interface\Buttons\UI-CheckBox-Check]]);
checkbox.checkedTexture:SetAllPoints();
checkbox.checkedTexture:Hide();
checkbox.disabledCheckedTexture = self:Texture(checkbox.target, nil, nil,
[[Interface\Buttons\UI-CheckBox-Check-Disabled]]);
checkbox.disabledCheckedTexture:SetAllPoints();
checkbox.disabledCheckedTexture:Hide();
for k, v in pairs(CheckboxMethods) do
checkbox[k] = v;
end
self:ApplyBackdrop(checkbox.target);
self:HookDisabledBackdrop(checkbox);
self:HookHoverBorder(checkbox);
if width == nil then
checkbox:AutoWidth();
end
for k, v in pairs(CheckboxEvents) do
checkbox:SetScript(k, v);
end
return checkbox;
end
----------------------------------------------------
--- IconCheckbox
----------------------------------------------------
function StdUi:IconCheckbox(parent, icon, text, width, height, iconSize)
iconSize = iconSize or 16
local checkbox = self:Checkbox(parent, text, width, height);
checkbox.icon = self:Texture(checkbox, iconSize, iconSize, icon);
checkbox.icon:SetPoint('LEFT', checkbox.target, 'RIGHT', 5, 0);
checkbox.text:ClearAllPoints();
checkbox.text:SetPoint('LEFT', checkbox.target, 'RIGHT', iconSize + 5, 0);
checkbox.text:SetPoint('RIGHT', checkbox, 'RIGHT', -5, 0);
return checkbox;
end
----------------------------------------------------
--- Radio
----------------------------------------------------
local RadioEvents = {
OnClick = function(self)
if not self.isDisabled then
self:SetChecked(true);
end
end
};
---@return CheckButton
function StdUi:Radio(parent, text, groupName, width, height)
local radio = self:Checkbox(parent, text, width, height);
radio.checkedTexture = self:Texture(radio.target, nil, nil, [[Interface\Buttons\UI-RadioButton]]);
radio.checkedTexture:SetAllPoints(radio.target);
radio.checkedTexture:Hide();
radio.checkedTexture:SetTexCoord(0.25, 0.5, 0, 1);
radio.disabledCheckedTexture = self:Texture(radio.target, nil, nil,
[[Interface\Buttons\UI-RadioButton]]);
radio.disabledCheckedTexture:SetAllPoints(radio.target);
radio.disabledCheckedTexture:Hide();
radio.disabledCheckedTexture:SetTexCoord(0.75, 1, 0, 1);
for k, v in pairs(RadioEvents) do
radio:SetScript(k, v);
end
if groupName then
self:AddToRadioGroup(radio, groupName);
end
return radio;
end
StdUi.radioGroups = {};
StdUi.radioGroupValues = {};
---@return CheckButton[]
function StdUi:RadioGroup(groupName)
if not self.radioGroups[groupName] then
self.radioGroups[groupName] = {};
end
if not self.radioGroupValues[groupName] then
self.radioGroupValues[groupName] = {};
end
return self.radioGroups[groupName];
end
function StdUi:GetRadioGroupValue(groupName)
local group = self:RadioGroup(groupName);
for i = 1, #group do
local radio = group[i];
if radio:GetChecked() then
return radio:GetValue();
end
end
return nil;
end
function StdUi:SetRadioGroupValue(groupName, value)
local group = self:RadioGroup(groupName);
for i = 1, #group do
local radio = group[i];
radio:SetChecked(radio.value == value)
end
return nil;
end
local radioGroupOnValueChanged = function(radio)
radio.notified = true;
local group = radio.radioGroup;
local groupName = radio.radioGroupName;
-- We must get all notifications from group
for i = 1, #group do
if not group[i].notified then
return
end
end
local newValue = radio.stdUi:GetRadioGroupValue(groupName);
if radio.stdUi.radioGroupValues[groupName] ~= newValue then
radio.OnValueChangedCallback(newValue, groupName);
end
radio.stdUi.radioGroupValues[groupName] = newValue;
for i = 1, #group do
group[i].notified = false;
end
end
function StdUi:OnRadioGroupValueChanged(groupName, callback)
local group = self:RadioGroup(groupName);
for i = 1, #group do
local radio = group[i];
radio.OnValueChangedCallback = callback;
radio.OnValueChanged = radioGroupOnValueChanged;
end
return nil;
end
local RadioGroupEvents = {
OnClick = function(radio)
for i = 1, #radio.radioGroup do
local otherRadio = radio.radioGroup[i];
if otherRadio ~= radio then
otherRadio:SetChecked(false);
end
end
end
};
function StdUi:AddToRadioGroup(radio, groupName)
local group = self:RadioGroup(groupName);
tinsert(group, radio);
radio.radioGroup = group;
radio.radioGroupName = groupName;
for k, v in pairs(RadioGroupEvents) do
radio:HookScript(k, v);
end
end
StdUi:RegisterModule(module, version);