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.
383 lines
10 KiB
383 lines
10 KiB
local _, addon = ...
|
|
local API = addon.API;
|
|
|
|
local MENU_PADDING_V = 8;
|
|
local MAX_BUTTON_PER_PAGE = 8;
|
|
local MENU_BUTTON_WIDTH = 120;
|
|
local MENU_BUTTON_HEIGHT = 24;
|
|
local MENU_BUTTON_MAX_WIDTH = 192;
|
|
local BUTTON_TEXT_OFFSET_X = 12;
|
|
local SCROLLBAR_PADDING = 8;
|
|
local SCROLLBAR_WIDTH = 12;
|
|
local SCROLLBAR_SIZE = SCROLLBAR_WIDTH + MENU_PADDING_V + SCROLLBAR_PADDING;
|
|
local BUTTON_TEXT_FONT = "DUIFont_Quest_Paragraph";
|
|
|
|
local UNBOUND_MENU_BUTTON_WIDTH = MENU_BUTTON_WIDTH;
|
|
local DEFAULT_MENU_WIDTH = MENU_BUTTON_WIDTH + SCROLLBAR_SIZE;
|
|
local DEFAULT_MENU_HEIGHT = MENU_BUTTON_HEIGHT * MAX_BUTTON_PER_PAGE;
|
|
|
|
local DropDownMenu;
|
|
local DropDownMenuMixin = {};
|
|
local UtilityFontString;
|
|
|
|
|
|
local MenuButtonMixin = {};
|
|
|
|
function MenuButtonMixin:OnLoad()
|
|
self:RegisterForClicks("LeftButtonUp", "RightButtonUp");
|
|
self.ButtonText = self:CreateFontString(nil, "OVERLAY", BUTTON_TEXT_FONT);
|
|
self.ButtonText:SetPoint("LEFT", self, "LEFT", BUTTON_TEXT_OFFSET_X, 0);
|
|
self.ButtonText:SetPoint("RIGHT", self, "RIGHT", -BUTTON_TEXT_OFFSET_X + 1, 0);
|
|
self.ButtonText:SetJustifyV("MIDDLE");
|
|
self.ButtonText:SetMaxLines(1);
|
|
self:SetTextAlignment("LEFT");
|
|
end
|
|
|
|
function MenuButtonMixin:SetButtonText(text)
|
|
self.ButtonText:SetText(text);
|
|
end
|
|
|
|
function MenuButtonMixin:SetData(data)
|
|
self:SetButtonText(data[1]);
|
|
self.ButtonText:SetFont(data[2], 12, "");
|
|
self.fontFile = data[2];
|
|
end
|
|
|
|
function MenuButtonMixin:OnClick(button)
|
|
if button == "LeftButton" then
|
|
addon.FontUtil:SetFontByFile(self.fontFile);
|
|
elseif button == "RightButton" then
|
|
DropDownMenu:Close();
|
|
end
|
|
end
|
|
|
|
function MenuButtonMixin:OnEnter()
|
|
DropDownMenu:HighlightButton(self);
|
|
end
|
|
|
|
function MenuButtonMixin:OnLeave()
|
|
DropDownMenu:HighlightButton(nil);
|
|
end
|
|
|
|
function MenuButtonMixin:SetTextAlignment(justifyH)
|
|
self.ButtonText:SetJustifyH(justifyH);
|
|
end
|
|
|
|
local function CreateMenuButton(parent)
|
|
local b = CreateFrame("Button", nil, parent);
|
|
API.Mixin(b, MenuButtonMixin);
|
|
|
|
b:SetScript("OnEnter", b.OnEnter);
|
|
b:SetScript("OnLeave", b.OnLeave);
|
|
b:SetScript("OnClick", b.OnClick);
|
|
|
|
b:OnLoad();
|
|
|
|
b:SetWidth(MENU_BUTTON_WIDTH);
|
|
b:SetHeight(MENU_BUTTON_HEIGHT);
|
|
|
|
return b
|
|
end
|
|
|
|
|
|
local ScrollViewDataProvider = {};
|
|
do
|
|
local OFFSET_PER_SCROLL = MENU_BUTTON_HEIGHT;
|
|
ScrollViewDataProvider.content = {};
|
|
ScrollViewDataProvider.numEntry = 0;
|
|
ScrollViewDataProvider.objects = {};
|
|
|
|
local function GetTextWidth(text)
|
|
if not UtilityFontString then
|
|
UtilityFontString = DropDownMenu:CreateFontString(nil, "BACKGROUND", BUTTON_TEXT_FONT);
|
|
UtilityFontString:SetJustifyH("LEFT");
|
|
UtilityFontString:SetPoint("TOP", DropDownMenu, "TOP", 0, 0);
|
|
UtilityFontString:Hide();
|
|
end
|
|
UtilityFontString:SetText(text);
|
|
return UtilityFontString:GetUnboundedStringWidth();
|
|
end
|
|
|
|
function ScrollViewDataProvider:GetSpacing()
|
|
return 0
|
|
end
|
|
|
|
function ScrollViewDataProvider:SetContent(content)
|
|
self.content = content;
|
|
self:CalculateAllExtent();
|
|
if self.isVisible then
|
|
self:UpdateView();
|
|
else
|
|
self.isDisplayDirty = true;
|
|
end
|
|
end
|
|
|
|
function ScrollViewDataProvider:CalculateAllExtent()
|
|
local fromOffset = MENU_PADDING_V;
|
|
|
|
self.extent = {};
|
|
self.extent[0] = 0 + fromOffset;
|
|
self.extent[1] = 0 + fromOffset;
|
|
|
|
local textWidth;
|
|
local maxTextWidth = 0;
|
|
|
|
for i = 1, #self.content do
|
|
self.extent[i + 1] = MENU_BUTTON_HEIGHT * i + fromOffset;
|
|
textWidth = GetTextWidth(self.content[i][1]);
|
|
if textWidth > maxTextWidth then
|
|
maxTextWidth = textWidth;
|
|
end
|
|
end
|
|
|
|
self.maxTextWidth = API.Round(2*BUTTON_TEXT_OFFSET_X + maxTextWidth);
|
|
end
|
|
ScrollViewDataProvider:CalculateAllExtent();
|
|
|
|
function ScrollViewDataProvider:GetExtent()
|
|
return self.extent
|
|
end
|
|
|
|
function ScrollViewDataProvider:UpdateView()
|
|
self.isDisplayDirty = nil;
|
|
self.owner:OnContentChanged();
|
|
end
|
|
|
|
function ScrollViewDataProvider:GetMaxDataIndex()
|
|
return #self.content
|
|
end
|
|
|
|
function ScrollViewDataProvider:GetStep()
|
|
return OFFSET_PER_SCROLL;
|
|
end
|
|
|
|
function ScrollViewDataProvider:GetMaxExtent()
|
|
return self.extent[#self.extent] + MENU_PADDING_V
|
|
end
|
|
|
|
function ScrollViewDataProvider:CreateObject()
|
|
local object = CreateMenuButton(DropDownMenu.ScrollView);
|
|
table.insert(self.objects, object);
|
|
return object
|
|
end
|
|
|
|
function ScrollViewDataProvider:SetObjectData(object, dataIndex)
|
|
if dataIndex ~= object.dataIndex then
|
|
object.dataIndex = dataIndex;
|
|
|
|
local data = self.content[dataIndex];
|
|
if data then
|
|
|
|
else
|
|
return false
|
|
end
|
|
|
|
object:SetData(data);
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function ScrollViewDataProvider:OnShow(scrollView)
|
|
self.isVisible = true;
|
|
if self.isDisplayDirty then
|
|
self:UpdateView();
|
|
end
|
|
end
|
|
|
|
function ScrollViewDataProvider:OnHide(scrollView)
|
|
self.isVisible = false;
|
|
end
|
|
|
|
function ScrollViewDataProvider:OnViewUpdated()
|
|
|
|
end
|
|
end
|
|
|
|
|
|
local function DropDown_OnLoad(self)
|
|
self:SetSize(8, 8);
|
|
|
|
self.textures = {};
|
|
|
|
local bg = self:CreateTexture(nil, "BACKGROUND");
|
|
table.insert(self.textures, bg);
|
|
self.Background = bg;
|
|
local margin = 12;
|
|
bg:SetTextureSliceMargins(margin, margin, margin, margin);
|
|
bg:SetTextureSliceMode(1);
|
|
bg:SetAllPoints(true);
|
|
bg:SetTexCoord(0, 0.25, 0, 0.25);
|
|
|
|
self.ButtonHighlight = CreateFrame("Frame", nil, self);
|
|
self.ButtonHighlight:Hide();
|
|
local hl = self.ButtonHighlight:CreateTexture(nil, "BACKGROUND", nil, 1);
|
|
table.insert(self.textures, hl);
|
|
local margin = 8;
|
|
hl:SetTextureSliceMargins(margin, margin, margin, margin);
|
|
hl:SetTextureSliceMode(1);
|
|
hl:SetTexCoord(0.265625, 0.515625, 0, 0.125);
|
|
hl:SetAllPoints(true);
|
|
|
|
local ScrollView = addon.CreateScrollView(self);
|
|
self.ScrollView = ScrollView;
|
|
ScrollView:SetPoint("TOPLEFT", self, "TOPLEFT", 0, -2);
|
|
ScrollView:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 0, 2);
|
|
|
|
local ScrollBar = addon.CreateScrollBar(self);
|
|
self.ScrollBar = ScrollBar;
|
|
local inset = SCROLLBAR_PADDING;
|
|
ScrollBar:SetPoint("TOPRIGHT", ScrollView, "TOPRIGHT", -inset, -inset);
|
|
ScrollBar:SetPoint("BOTTOMRIGHT", ScrollView, "BOTTOMRIGHT", -inset, inset);
|
|
ScrollBar:SetOwner(ScrollView);
|
|
ScrollBar:SetAlwaysVisible(false);
|
|
ScrollBar:ShowScrollToBottomButton(false);
|
|
ScrollBar:SetTheme(1);
|
|
ScrollBar:Show();
|
|
|
|
ScrollView:SetScrollBar(ScrollBar);
|
|
|
|
self:LoadTheme();
|
|
end
|
|
|
|
function DropDownMenuMixin:OnHide()
|
|
self:Hide();
|
|
end
|
|
|
|
function DropDownMenuMixin:LoadTheme()
|
|
if self.textures then
|
|
local file = addon.ThemeUtil:GetTextureFile("DropDown-UI.png");
|
|
for _, texture in pairs(self.textures) do
|
|
texture:SetTexture(file);
|
|
end
|
|
|
|
if addon.ThemeUtil:IsDarkMode() then
|
|
self.ScrollBar:SetTheme(2);
|
|
else
|
|
self.ScrollBar:SetTheme(1);
|
|
end
|
|
end
|
|
end
|
|
|
|
function DropDownMenuMixin:HighlightButton(button)
|
|
self.ButtonHighlight:Hide();
|
|
self.ButtonHighlight:ClearAllPoints();
|
|
|
|
if button and button:IsEnabled() then
|
|
self.ButtonHighlight:SetParent(button);
|
|
self.ButtonHighlight:SetPoint("TOPLEFT", button, "TOPLEFT", 2, 0);
|
|
self.ButtonHighlight:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -2, 0);
|
|
self.ButtonHighlight:SetFrameLevel(button:GetFrameLevel());
|
|
self.ButtonHighlight:Show();
|
|
end
|
|
end
|
|
|
|
function DropDownMenuMixin:SetContent(content)
|
|
ScrollViewDataProvider:SetContent(content);
|
|
self.ScrollView:OnContentChanged();
|
|
self.ScrollView:ScrollToTop();
|
|
self:Layout();
|
|
end
|
|
|
|
function DropDownMenuMixin:Layout()
|
|
local height;
|
|
local contentHeight = self.ScrollView:GetMaxExtent();
|
|
|
|
if contentHeight > DEFAULT_MENU_HEIGHT then
|
|
height = DEFAULT_MENU_HEIGHT;
|
|
else
|
|
height = contentHeight;
|
|
end
|
|
|
|
self:SetHeight(height);
|
|
|
|
self.ScrollView:OnSizeChanged();
|
|
self.ScrollBar:OnSizeChanged();
|
|
self.ScrollView:UpdateScrollRange();
|
|
self.ScrollBar:UpdateThumbSize();
|
|
|
|
local maxTextWidth = ScrollViewDataProvider.maxTextWidth;
|
|
local menuButtonWidth;
|
|
|
|
if maxTextWidth > MENU_BUTTON_MAX_WIDTH then
|
|
menuButtonWidth = MENU_BUTTON_MAX_WIDTH;
|
|
else
|
|
menuButtonWidth = maxTextWidth;
|
|
end
|
|
|
|
local width;
|
|
|
|
if self.ScrollView:IsScrollable() then
|
|
width = menuButtonWidth + SCROLLBAR_SIZE;
|
|
else
|
|
width = menuButtonWidth;
|
|
end
|
|
|
|
self:SetWidth(width);
|
|
|
|
MENU_BUTTON_WIDTH = menuButtonWidth;
|
|
|
|
for _, object in pairs(ScrollViewDataProvider.objects) do
|
|
object:SetWidth(menuButtonWidth)
|
|
end
|
|
end
|
|
|
|
function DropDownMenuMixin:Close()
|
|
self:Hide();
|
|
end
|
|
|
|
local function GetDropDownMenu(parent)
|
|
if not DropDownMenu then
|
|
local f = CreateFrame("Frame", nil, parent);
|
|
f:EnableMouse(true);
|
|
API.Mixin(f, DropDownMenuMixin);
|
|
|
|
DropDown_OnLoad(f);
|
|
|
|
f:SetPoint("CENTER", nil, "CENTER", 0, 0);
|
|
f:SetSize(DEFAULT_MENU_WIDTH, DEFAULT_MENU_HEIGHT);
|
|
f.ScrollView:OnSizeChanged();
|
|
f.ScrollBar:OnSizeChanged();
|
|
|
|
f:SetScript("OnHide", f.OnHide);
|
|
f.ScrollView:SetDataProvider(ScrollViewDataProvider);
|
|
|
|
DropDownMenu = f;
|
|
end
|
|
|
|
return DropDownMenu
|
|
end
|
|
addon.GetDropDownMenu = GetDropDownMenu;
|
|
|
|
|
|
do
|
|
--Debug
|
|
local content1 = {
|
|
{"Test 1", 1},
|
|
{"Test 2", 1},
|
|
{"Test 3", 1},
|
|
{"Test 4", 1},
|
|
{"Test 5", 1},
|
|
{"Test 6", 1},
|
|
{"Test 7", 1},
|
|
{"Test 8", 1},
|
|
--{"Test 9", 1},
|
|
--{"Test 10", 1},
|
|
--{"Test 11", 1},
|
|
};
|
|
|
|
local content2 = {
|
|
{"Test 1", 1},
|
|
{"Test 2", 1},
|
|
{"Test 3", 1},
|
|
{"Test 4", 1},
|
|
{"Test 5", 1},
|
|
{"Test 6", 1},
|
|
{"Test 7", 1},
|
|
{"Test 8", 1},
|
|
{"Test 9", 1},
|
|
{"Test 10", 1},
|
|
{"Test 11", 1},
|
|
{"Test 12", 1},
|
|
};
|
|
end
|