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/EditBox.lua

390 lines
9.1 KiB

--- @type StdUi
local StdUi = LibStub and LibStub('StdUi', true);
if not StdUi then
return
end
local module, version = 'EditBox', 9;
if not StdUi:UpgradeNeeded(module, version) then return end;
local pairs = pairs;
local strlen = strlen;
----------------------------------------------------
--- SimpleEditBox
----------------------------------------------------
local SimpleEditBoxMethods = {
SetFontSize = function(self, newSize)
self:SetFont(self:GetFont(), newSize, self.stdUi.config.font.effect);
end
};
local SimpleEditBoxEvents = {
OnEscapePressed = function (self)
self:ClearFocus();
end
}
--- @return EditBox
function StdUi:SimpleEditBox(parent, width, height, text)
--- @type EditBox
local editBox = CreateFrame('EditBox', nil, parent);
editBox.stdUi = self;
self:InitWidget(editBox);
editBox:SetTextInsets(3, 3, 3, 3);
editBox:SetFontObject(ChatFontNormal);
editBox:SetAutoFocus(false);
for k, v in pairs(SimpleEditBoxMethods) do
editBox[k] = v;
end
for k, v in pairs(SimpleEditBoxEvents) do
editBox:SetScript(k, v);
end
if text then
editBox:SetText(text);
end
self:HookDisabledBackdrop(editBox);
self:HookHoverBorder(editBox);
self:ApplyBackdrop(editBox);
self:SetObjSize(editBox, width, height);
return editBox;
end
----------------------------------------------------
--- ApplyPlaceholder
----------------------------------------------------
local ApplyPlaceholderOnTextChanged = function(self)
if strlen(self:GetText()) > 0 then
self.placeholder.icon:Hide();
self.placeholder.label:Hide();
else
self.placeholder.icon:Show();
self.placeholder.label:Show();
end
end
function StdUi:ApplyPlaceholder(widget, placeholderText, icon, iconColor)
widget.placeholder = {};
local label = self:Label(widget, placeholderText);
self:SetTextColor(label, 'disabled');
widget.placeholder.label = label;
if icon then
local texture = self:Texture(widget, 14, 14, icon);
local c = iconColor or self.config.font.color.disabled;
texture:SetVertexColor(c.r, c.g, c.b, c.a);
self:GlueLeft(texture, widget, 5, 0, true);
self:GlueRight(label, texture, 2, 0);
widget.placeholder.icon = texture;
else
self:GlueLeft(label, widget, 2, 0, true);
end
widget:HookScript('OnTextChanged', ApplyPlaceholderOnTextChanged);
end
----------------------------------------------------
--- SearchEditBox
----------------------------------------------------
local SearchEditBoxOnTextChanged = function(self)
if self.OnValueChanged then
self:OnValueChanged(self:GetText());
end
end
function StdUi:SearchEditBox(parent, width, height, placeholderText)
local editBox = self:SimpleEditBox(parent, width, height, '');
editBox:SetScript('OnTextChanged', SearchEditBoxOnTextChanged);
self:ApplyPlaceholder(editBox, placeholderText, [[Interface\Common\UI-Searchbox-Icon]]);
return editBox;
end
----------------------------------------------------
--- SearchEditBox
----------------------------------------------------
local EditBoxMethods = {
GetValue = function(self)
return self.value;
end,
SetValue = function(self, value)
self.value = value;
self:SetText(value);
self:Validate();
self.button:Hide();
end,
IsValid = function(self)
return self.isValid;
end,
Validate = function(self)
self.isValidated = true;
self.isValid = self.validator(self);
if self.isValid then
if self.button then
self.button:Hide();
end
if self.OnValueChanged and tostring(self.lastValue) ~= tostring(self.value) then
self:OnValueChanged(self.value);
self.lastValue = self.value;
end
end
self.isValidated = false;
end;
}
local EditBoxButtonOnClick = function(self)
self.editBox:Validate(self.editBox);
end
local EditBoxEvents = {
OnEnterPressed = function(self)
self:Validate();
end,
OnTextChanged = function(self, isUserInput)
local value = StdUi.Util.stripColors(self:GetText());
if tostring(value) ~= tostring(self.value) then
if not self.isValidated and self.button and isUserInput then
self.button:Show();
end
else
self.button:Hide();
end
end
}
--- @return EditBox
function StdUi:EditBox(parent, width, height, text, validator)
validator = validator or StdUi.Util.editBoxValidator;
local editBox = self:SimpleEditBox(parent, width, height, text);
editBox.validator = validator;
local button = self:Button(editBox, 40, height - 4, OKAY);
button:SetPoint('RIGHT', -2, 0);
button:Hide();
button.editBox = editBox;
editBox.button = button;
for k, v in pairs(EditBoxMethods) do
editBox[k] = v;
end
button:SetScript('OnClick', EditBoxButtonOnClick);
for k, v in pairs(EditBoxEvents) do
editBox:SetScript(k, v);
end
return editBox;
end
----------------------------------------------------
--- SearchEditBox
----------------------------------------------------
local NumericBoxMethods = {
SetMaxValue = function(self, value)
self.maxValue = value;
self:Validate();
end;
SetMinValue = function(self, value)
self.minValue = value;
self:Validate();
end;
SetMinMaxValue = function(self, min, max)
self.minValue = min;
self.maxValue = max;
self:Validate();
end
}
function StdUi:NumericBox(parent, width, height, text, validator)
validator = validator or self.Util.numericBoxValidator;
local editBox = self:EditBox(parent, width, height, text, validator);
editBox:SetNumeric(true);
for k, v in pairs(NumericBoxMethods) do
editBox[k] = v;
end
return editBox;
end
----------------------------------------------------
--- MoneyBox
----------------------------------------------------
local MoneyBoxMethods = {
SetValue = function(self, value)
self.value = value;
local formatted = self.stdUi.Util.formatMoney(value);
self:SetText(formatted);
self:Validate();
self.button:Hide();
end;
};
function StdUi:MoneyBox(parent, width, height, text, validator, excludeCopper)
if excludeCopper then
validator = validator or self.Util.moneyBoxValidatorExC;
else
validator = validator or self.Util.moneyBoxValidator;
end
local editBox = self:EditBox(parent, width, height, text, validator);
editBox.stdUi = self;
editBox:SetMaxLetters(20);
for k, v in pairs(MoneyBoxMethods) do
editBox[k] = v;
end
return editBox;
end
----------------------------------------------------
--- MultiLineBox
----------------------------------------------------
local MultiLineBoxMethods = {
SetValue = function(self, value)
self.editBox:SetText(value);
if self.OnValueChanged then
self:OnValueChanged(value);
end
end,
GetValue = function(self)
return self.editBox:GetText();
end,
SetFont = function(self, font, size, flags)
self.editBox:SetFont(font, size, flags);
end,
Enable = function(self)
self.editBox:Enable();
end,
Disable = function(self)
self.editBox:Disable();
end,
SetFocus = function(self)
self.editBox:SetFocus();
end,
ClearFocus = function(self)
self.editBox:ClearFocus();
end,
HasFocus = function(self)
return self.editBox:HasFocus();
end
};
local MultiLineBoxOnCursorChanged = function(self, _, y, _, cursorHeight)
local sf, newY = self.scrollFrame, -y;
local offset = sf:GetVerticalScroll();
if newY < offset then
sf:SetVerticalScroll(newY);
else
newY = newY + cursorHeight - sf:GetHeight() + 6; --text insets
if newY > offset then
sf:SetVerticalScroll(math.ceil(newY));
end
end
end
local MultiLineBoxOnTextChanged = function(self)
if self.panel.OnValueChanged then
self.panel.OnValueChanged(self.panel, self:GetText());
end
end
local MultiLineBoxScrollOnMouseDown = function(self, button)
self.scrollChild:SetFocus();
end
local MultiLineBoxScrollOnVerticalScroll = function(self, offset)
self.scrollChild:SetHitRectInsets(0, 0, offset, self.scrollChild:GetHeight() - offset - self:GetHeight());
end
function StdUi:MultiLineBox(parent, width, height, text)
local editBox = CreateFrame('EditBox');
local widget = self:ScrollFrame(parent, width, height, editBox);
editBox.stdUi = self;
local scrollFrame = widget.scrollFrame;
scrollFrame.editBox = editBox;
widget.editBox = editBox;
editBox.panel = widget;
self:ApplyBackdrop(widget, 'button');
self:HookHoverBorder(scrollFrame);
self:HookHoverBorder(editBox);
editBox:SetWidth(scrollFrame:GetWidth());
self:GlueAcross(scrollFrame, widget, 2, -2, -widget.scrollBarWidth - 2, 3);
--editBox:SetHeight(scrollFrame:GetHeight());
editBox:SetTextInsets(3, 3, 3, 3);
editBox:SetFontObject(ChatFontNormal);
editBox:SetAutoFocus(false);
editBox:SetScript('OnEscapePressed', editBox.ClearFocus);
editBox:SetMultiLine(true);
editBox:EnableMouse(true);
editBox:SetAutoFocus(false);
editBox:SetCountInvisibleLetters(false);
editBox:SetAllPoints();
editBox.scrollFrame = scrollFrame;
editBox.panel = widget;
for k, v in pairs(MultiLineBoxMethods) do
widget[k] = v;
end
if text then
editBox:SetText(text);
end
editBox:SetScript('OnCursorChanged', MultiLineBoxOnCursorChanged)
editBox:SetScript('OnTextChanged', MultiLineBoxOnTextChanged);
scrollFrame:HookScript('OnMouseDown', MultiLineBoxScrollOnMouseDown);
scrollFrame:HookScript('OnVerticalScroll', MultiLineBoxScrollOnVerticalScroll);
widget.SetText = widget.SetValue;
widget.GetText = widget.GetValue;
return widget;
end
StdUi:RegisterModule(module, version);