AUTOCOMPLETE_MAX_BUTTONS = 5;
AUTOCOMPLETE_FLAG_NONE = 0x00000000;
AUTOCOMPLETE_FLAG_IN_GROUP = 0x00000001;
AUTOCOMPLETE_FLAG_IN_GUILD = 0x00000002;
AUTOCOMPLETE_FLAG_FRIEND = 0x00000004;
AUTOCOMPLETE_FLAG_BNET = 0x00000008;
AUTOCOMPLETE_FLAG_INTERACTED_WITH = 0x00000010;
AUTOCOMPLETE_FLAG_ONLINE = 0x00000020;
AUTOCOMPLETE_FLAG_ALL = 0xffffffff;
AUTOCOMPLETE_LIST_TEMPLATES = {
ALL = {
include = AUTOCOMPLETE_FLAG_ALL,
exclude = AUTOCOMPLETE_FLAG_NONE,
},
ALL_CHARS = {
include = AUTOCOMPLETE_FLAG_ALL,
exclude = AUTOCOMPLETE_FLAG_BNET,
},
ONLINE = {
include = AUTOCOMPLETE_FLAG_ONLINE,
exclude = AUTOCOMPLETE_FLAG_NONE,
},
ONLINE_NOT_BNET = {
include = AUTOCOMPLETE_FLAG_ONLINE,
exclude = AUTOCOMPLETE_FLAG_BNET,
},
ONLINE_NOT_IN_GROUP = {
include = AUTOCOMPLETE_FLAG_ONLINE,
exclude = bit.bor(AUTOCOMPLETE_FLAG_IN_GROUP,AUTOCOMPLETE_FLAG_BNET),
},
ONLINE_NOT_IN_GUILD = {
include = AUTOCOMPLETE_FLAG_ONLINE,
exclude = bit.bor(AUTOCOMPLETE_FLAG_IN_GUILD,AUTOCOMPLETE_FLAG_BNET),
},
NOT_FRIEND = {
include = AUTOCOMPLETE_FLAG_ALL,
exclude = bit.bor(AUTOCOMPLETE_FLAG_FRIEND,AUTOCOMPLETE_FLAG_BNET);
},
IN_GROUP = {
include = AUTOCOMPLETE_FLAG_IN_GROUP,
exclude = AUTOCOMPLETE_FLAG_BNET,
},
IN_GUILD = {
include = AUTOCOMPLETE_FLAG_IN_GUILD,
exclude = AUTOCOMPLETE_FLAG_BNET,
},
FRIEND = {
include = AUTOCOMPLETE_FLAG_FRIEND,
exclude = AUTOCOMPLETE_FLAG_BNET,
},
FRIEND_NOT_GUILD = {
include = AUTOCOMPLETE_FLAG_FRIEND,
exclude = bit.bor(AUTOCOMPLETE_FLAG_IN_GUILD,AUTOCOMPLETE_FLAG_BNET),
},
FRIEND_AND_GUILD = {
include = bit.bor(AUTOCOMPLETE_FLAG_FRIEND, AUTOCOMPLETE_FLAG_IN_GUILD),
exclude = AUTOCOMPLETE_FLAG_BNET,
},
}
AUTOCOMPLETE_LIST = {};
local AUTOCOMPLETE_LIST = AUTOCOMPLETE_LIST;
AUTOCOMPLETE_LIST.ALL = AUTOCOMPLETE_LIST_TEMPLATES.ALL;
AUTOCOMPLETE_LIST.WHISPER = AUTOCOMPLETE_LIST_TEMPLATES.ONLINE_NOT_BNET;
AUTOCOMPLETE_LIST.SMART_WHISPER = AUTOCOMPLETE_LIST_TEMPLATES.ONLINE;
AUTOCOMPLETE_LIST.WHISPER_EXTRACT = AUTOCOMPLETE_LIST_TEMPLATES.ALL_CHARS;
AUTOCOMPLETE_LIST.SMART_WHISPER_EXTRACT=AUTOCOMPLETE_LIST_TEMPLATES.ALL;
AUTOCOMPLETE_LIST.INVITE = AUTOCOMPLETE_LIST_TEMPLATES.ONLINE_NOT_IN_GROUP;
AUTOCOMPLETE_LIST.UNINVITE = AUTOCOMPLETE_LIST_TEMPLATES.IN_GROUP;
AUTOCOMPLETE_LIST.PROMOTE = AUTOCOMPLETE_LIST_TEMPLATES.IN_GROUP;
AUTOCOMPLETE_LIST.TEAM_INVITE = AUTOCOMPLETE_LIST_TEMPLATES.ONLINE_NOT_BNET;
AUTOCOMPLETE_LIST.GUILD_INVITE = AUTOCOMPLETE_LIST_TEMPLATES.ONLINE_NOT_IN_GUILD;
AUTOCOMPLETE_LIST.GUILD_UNINVITE = AUTOCOMPLETE_LIST_TEMPLATES.IN_GUILD;
AUTOCOMPLETE_LIST.GUILD_PROMOTE = AUTOCOMPLETE_LIST_TEMPLATES.IN_GUILD;
AUTOCOMPLETE_LIST.GUILD_DEMOTE = AUTOCOMPLETE_LIST_TEMPLATES.IN_GUILD;
AUTOCOMPLETE_LIST.GUILD_LEADER = AUTOCOMPLETE_LIST_TEMPLATES.IN_GUILD;
AUTOCOMPLETE_LIST.ADDFRIEND = AUTOCOMPLETE_LIST_TEMPLATES.NOT_FRIEND;
AUTOCOMPLETE_LIST.REMOVEFRIEND = AUTOCOMPLETE_LIST_TEMPLATES.FRIEND;
AUTOCOMPLETE_LIST.CHANINVITE = AUTOCOMPLETE_LIST_TEMPLATES.ONLINE_NOT_BNET;
AUTOCOMPLETE_LIST.MAIL = AUTOCOMPLETE_LIST_TEMPLATES.ALL_CHARS;
AUTOCOMPLETE_LIST.CALENDARGUILDEVENT= AUTOCOMPLETE_LIST_TEMPLATES.FRIEND_NOT_GUILD;
AUTOCOMPLETE_LIST.CALENDAREVENT = AUTOCOMPLETE_LIST_TEMPLATES.FRIEND_AND_GUILD;
AUTOCOMPLETE_SIMPLE_REGEX = "(.+)";
AUTOCOMPLETE_SIMPLE_FORMAT_REGEX = "%1$s";
AUTOCOMPLETE_DEFAULT_Y_OFFSET = 3;
function AutoComplete_OnLoad(self)
self:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b);
self:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b);
self.maxHeight = AUTOCOMPLETE_MAX_BUTTONS * AutoCompleteButton1:GetHeight();
AutoCompleteInstructions:SetText("|cffbbbbbb"..PRESS_TAB.."|r");
end
function AutoComplete_Update(parent, text, cursorPosition)
local self = AutoCompleteBox;
local attachPoint;
if ( not parent.autoCompleteParams ) then
return;
end
if ( not text or text == "" ) then
AutoComplete_HideIfAttachedTo(parent);
return;
end
if ( cursorPosition <= strlen(text) ) then
self:SetParent(parent);
if(self.parent ~= parent) then
AutoComplete_SetSelectedIndex(self, 0);
end
if ( parent:GetBottom() - self.maxHeight <= (AUTOCOMPLETE_DEFAULT_Y_OFFSET + 10) ) then --10 is a magic number from the offset of AutoCompleteButton1.
attachPoint = "ABOVE";
else
attachPoint = "BELOW";
end
if ( (self.parent ~= parent) or (self.attachPoint ~= attachPoint) ) then
if ( attachPoint == "ABOVE" ) then
self:ClearAllPoints();
self:SetPoint("BOTTOMLEFT", parent, "TOPLEFT", parent.autoCompleteXOffset or 0, parent.autoCompleteYOffset or -AUTOCOMPLETE_DEFAULT_Y_OFFSET);
elseif ( attachPoint == "BELOW" ) then
self:ClearAllPoints();
self:SetPoint("TOPLEFT", parent, "BOTTOMLEFT", parent.autoCompleteXOffset or 0, parent.autoCompleteYOffset or AUTOCOMPLETE_DEFAULT_Y_OFFSET);
end
self.attachPoint = attachPoint;
end
self.parent = parent;
--We ask for one more result than we need so that we know whether or not results are continued
AutoComplete_UpdateResults(self,
GetAutoCompleteResults(text, parent.autoCompleteParams.include, parent.autoCompleteParams.exclude, AUTOCOMPLETE_MAX_BUTTONS+1, cursorPosition));
else
AutoComplete_HideIfAttachedTo(parent);
end
end
function AutoComplete_HideIfAttachedTo(parent)
local self = AutoCompleteBox;
if ( self.parent == parent ) then
self:Hide();
end
end
function AutoComplete_SetSelectedIndex(self, index)
self.selectedIndex = index;
for i=1, AUTOCOMPLETE_MAX_BUTTONS do
_G["AutoCompleteButton"..i]:UnlockHighlight();
end
if ( index ~= 0 ) then
_G["AutoCompleteButton"..index]:LockHighlight();
end
end
function AutoComplete_GetSelectedIndex(self)
return self.selectedIndex;
end
function AutoComplete_GetNumResults(self)
return self.numResults;
end
function AutoComplete_UpdateResults(self, ...)
local totalReturns = select("#", ...);
local numReturns = min(totalReturns, AUTOCOMPLETE_MAX_BUTTONS);
local maxWidth = 120;
for i=1, numReturns do
local button = _G["AutoCompleteButton"..i]
button:SetText(select(i, ...));
maxWidth = max(maxWidth, button:GetFontString():GetWidth()+30);
button:Enable();
button:Show();
end
for i = numReturns+1, AUTOCOMPLETE_MAX_BUTTONS do
_G["AutoCompleteButton"..i]:Hide();
end
if ( numReturns > 0 ) then
if ( not self:IsShown() ) then
AutoComplete_SetSelectedIndex(self, 0);
end
maxWidth = max(maxWidth, AutoCompleteInstructions:GetStringWidth()+30);
self:SetHeight(numReturns*AutoCompleteButton1:GetHeight()+35);
self:SetWidth(maxWidth);
self:Show();
else
self:Hide();
end
if ( totalReturns > AUTOCOMPLETE_MAX_BUTTONS ) then
local button = _G["AutoCompleteButton"..AUTOCOMPLETE_MAX_BUTTONS];
button:SetText(CONTINUED);
button:Disable();
self.numResults = numReturns - 1;
else
self.numResults = numReturns;
end
end
function AutoCompleteEditBox_OnTabPressed(editBox)
local autoComplete = AutoCompleteBox;
if ( autoComplete:IsShown() and autoComplete.parent == editBox ) then
local selectedIndex = AutoComplete_GetSelectedIndex(autoComplete);
local numReturns = AutoComplete_GetNumResults(autoComplete);
if ( IsShiftKeyDown() ) then
local nextNum = mod(selectedIndex - 1, numReturns);
if ( nextNum == 0 ) then
nextNum = numReturns;
end
AutoComplete_SetSelectedIndex(autoComplete, nextNum);
else
local nextNum = mod(selectedIndex + 1, numReturns);
if ( nextNum == 0 ) then
nextNum = numReturns;
end
AutoComplete_SetSelectedIndex(autoComplete, nextNum)
end
return true;
end
return false;
end
function AutoCompleteEditBox_OnEnterPressed(self)
local autoComplete = AutoCompleteBox;
if ( autoComplete:IsShown() and (autoComplete.parent == self) and (AutoComplete_GetSelectedIndex(autoComplete) ~= 0) ) then
AutoCompleteButton_OnClick(_G["AutoCompleteButton"..AutoComplete_GetSelectedIndex(autoComplete)]);
return true;
end
return false;
end
function AutoCompleteEditBox_OnTextChanged(self, userInput)
if ( userInput ) then
AutoComplete_Update(self, self:GetText(), self:GetUTF8CursorPosition());
end
if(self:GetText() == "") then
AutoComplete_HideIfAttachedTo(self);
end
end
function AutoCompleteEditBox_AddHighlightedText(editBox, text)
if ( not editBox.autoCompleteParams ) then
return;
end
local editBoxText = editBox:GetText();
local utf8Position = editBox:GetUTF8CursorPosition();
local nameToShow = GetAutoCompleteResults(text, editBox.autoCompleteParams.include, editBox.autoCompleteParams.exclude, 1, utf8Position);
if ( nameToShow ) then
--We're going to be setting the text programatically which will clear the userInput flag on the editBox. So we want to manually update the dropdown before we change the text.
AutoComplete_Update(editBox, editBoxText, utf8Position);
local newText = string.gsub(editBoxText, editBox.autoCompleteRegex or AUTOCOMPLETE_SIMPLE_REGEX,
string.format(editBox.autoCompleteFormatRegex or AUTOCOMPLETE_SIMPLE_FORMAT_REGEX, nameToShow,
string.match(editBoxText, editBox.autoCompleteRegex or AUTOCOMPLETE_SIMPLE_REGEX)),
1)
editBox:SetText(newText);
editBox:HighlightText(strlen(editBoxText), strlen(newText)); --This won't work if there is more after the name, but we aren't enabling this for normal chat (yet). Please fix me when we do.
editBox:SetCursorPosition(strlen(editBoxText));
end
end
function AutoCompleteEditBox_OnChar(self)
if (self.addHighlightedText and self:GetUTF8CursorPosition() == strlenutf8(self:GetText())) then
AutoCompleteEditBox_AddHighlightedText(self, self:GetText());
end
end
function AutoCompleteEditBox_OnEditFocusLost(self)
AutoComplete_HideIfAttachedTo(self);
end
function AutoCompleteEditBox_OnEscapePressed(self)
local autoComplete = AutoCompleteBox;
if ( autoComplete:IsShown() and autoComplete.parent == self ) then
AutoComplete_HideIfAttachedTo(self);
return true;
end
return false;
end
function AutoCompleteButton_OnClick(self)
local autoComplete = self:GetParent();
local editBox = autoComplete.parent;
local editBoxText = editBox:GetText();
--The following is used to replace "/whisper ar message here" with "/whisper Arenai message here"
local newText = string.gsub(editBoxText, editBox.autoCompleteRegex or AUTOCOMPLETE_SIMPLE_REGEX,
string.format(editBox.autoCompleteFormatRegex or AUTOCOMPLETE_SIMPLE_FORMAT_REGEX, self:GetText(),
string.match(editBoxText, editBox.autoCompleteRegex or AUTOCOMPLETE_SIMPLE_REGEX)),
1);
if ( editBox.addSpaceToAutoComplete ) then
newText = newText.." ";
end
editBox:SetText(newText);
--When we change the text, we move to the end, so we'll be consistent and move to the end if we don't change it as well.
editBox:SetCursorPosition(strlen(newText));
autoComplete:Hide();
end