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.

1670 lines
56 KiB

local _, addon = ...
local L = addon.L;
local API = addon.API;
local Clamp = API.Clamp;
local ThemeUtil = addon.ThemeUtil;
local InCombatLockdown = InCombatLockdown;
local CreateFrame = CreateFrame;
local type = type;
local GetDBValue = addon.GetDBValue;
local SetDBValue = addon.SetDBValue;
local INPUT_DEVICE_GAME_PAD = false;
local INPUT_DEVICE_ID = 1;
local GAME_PAD_ACTIVE = false;
local BUTTON_PADDING_LARGE = 12;
local FONT_HEIGHT_LARGE = 12;
local FONT_HEIGHT_NORMAL = 12;
local FRAME_PADDING = 14;
local OPTIONBUTTON_HEIGHT = 36; --Adaptive
local OPTIONBUTTON_WIDTH = OPTIONBUTTON_HEIGHT*12; --Adaptive
local OPTIONBUTTON_FROM_Y = 4;
local OPTIONBUTTON_LABEL_OFFSET = 14;
local OPTION_WIDGET_SIZE = 24;
local NUM_VISIBLE_OPTIONS = 10.5;
local ARROWOPTION_VALUETEXT_OFFSET_Y = -2;
local ARROWOTPION_WIDTH_RATIO = 7; --Adaptive
local ARROWOTPION_BAR_HEIGHT = 5; --Adaptive
local ARROWOTPION_CYCLING = false;
local HOTKEYFRAME_VALUETEXT_GAP = 4;
local TAB_BUTTON_GAP = 4;
local DISABLED_TEXTURE_ALPHA = 0.2;
local PREVIEW_PATH = "Interface/AddOns/DialogueUI/Art/PreviewPicture/";
local MainFrame;
local function Reposition_OnDragStart(self)
if self.OnMouseUp then
self:OnMouseUp();
end
MainFrame:StartMoving();
end
local function Reposition_OnDragStop(self)
MainFrame:StopMovingOrSizing();
MainFrame:UpdateScrollFrameBound();
end
local function SetupRepositionObject(obj)
obj:SetScript("OnDragStart", Reposition_OnDragStart);
obj:SetScript("OnDragStop", Reposition_OnDragStop);
obj:RegisterForDrag("LeftButton");
end
DUIDialogSettingsMixin = {};
function DUIDialogSettingsMixin:OnLoad()
MainFrame = self;
addon.SettingsUI = self;
addon.PixelUtil:AddPixelPerfectObject(self);
SetupRepositionObject(self.Header);
end
function DUIDialogSettingsMixin:OnShow_First()
if self.Init then
self:Init();
end
self:Layout();
self:UpdatePixel();
self:SetScript("OnShow", self.OnShow);
self.tabID = 1;
self:OnShow();
end
function DUIDialogSettingsMixin:OnShow()
self:UpdateCurrentTab();
self:EnableGamePadButton(true);
self:RegisterEvent("GAME_PAD_ACTIVE_CHANGED");
self:RegisterEvent("GAME_PAD_DISCONNECTED");
self:MoveToBestPosition();
addon.CallbackRegistry:Trigger("SettingsUI.Show");
end
function DUIDialogSettingsMixin:MoveToBestPosition()
if addon.DialogueUI:IsShown() then
local viewportWidth, viewportHeight = WorldFrame:GetSize(); --height unaffected by screen resolution
viewportWidth = math.min(viewportWidth, viewportHeight * 16/9);
local frameWidth = self:GetWidth();
self:ClearAllPoints();
self:SetPoint("CENTER", nil, "CENTER", 0.5*frameWidth -0.5 * viewportWidth + 16, 0);
else
self:ClearAllPoints();
self:SetPoint("CENTER", nil, "CENTER", 0, 0);
end
self:UpdateScrollFrameBound();
end
function DUIDialogSettingsMixin:UpdateScrollFrameBound()
self.scrollFrameTop = self.ScrollFrame:GetTop();
self.scrollFrameBottom = self.ScrollFrame:GetBottom();
end
function DUIDialogSettingsMixin:OnKeyDown(key)
local valid = false;
if key == "ESCAPE" or key == "F1" then
self:Hide();
valid = true;
end
if not InCombatLockdown() then
self:SetPropagateKeyboardInput(not valid);
end
end
function DUIDialogSettingsMixin:OnGamePadButtonDown(button)
--print(button)
GAME_PAD_ACTIVE = true;
local valid = false;
if button == "PADFORWARD" or button == "PADBACK" or button == "PAD2" then
self:Hide();
valid = true;
elseif button == "PADLSHOULDER" then
self:SelectTabByDelta(-1);
valid = true;
elseif button == "PADRSHOULDER" then
self:SelectTabByDelta(1);
valid = true;
elseif button == "PADDUP" then
self:FocusObjectByDelta(1);
valid = true;
elseif button == "PADDDOWN" then
self:FocusObjectByDelta(-1);
valid = true;
elseif button == "PADDLEFT" or button == "PADDRIGHT" or button == "PAD1" then
self:ClickFocusedObject(button);
valid = true;
end
if not InCombatLockdown() then
self:SetPropagateKeyboardInput(not valid);
end
end
function DUIDialogSettingsMixin:OnMouseWheel(delta)
end
function DUIDialogSettingsMixin:LoadTheme()
if self.Init then return end;
local filePath = ThemeUtil:GetTexturePath();
self.Background:SetTexture(filePath.."Settings-Background.png");
self.BackgroundShadow:SetTexture(filePath.."Settings-BackgroundShadow.png");
self.HeaderDivider:SetTexture(filePath.."Settings-Divider-H.png");
self.VerticalDivider:SetTexture(filePath.."Settings-Divider-V.png");
self.PreviewBorder:SetTexture(filePath.."Settings-PreviewBorder.png");
self.Header.Selection:SetTexture(filePath.."Settings-TabButton-Selection.png");
self.ButtonHighlight.BackTexture:SetTexture(filePath.."Settings-ButtonHighlight.png");
local file1 = filePath.."Settings-CloseButton.png";
self.Header.CloseButton.Background:SetTexture(file1);
self.Header.CloseButton.Highlight:SetTexture(file1);
self.Header.CloseButton.Icon:SetTexture(file1);
local file2 = filePath.."Settings-Checkbox.png";
self.checkboxPool:ProcessAllObjects(function(widget)
widget:SetTexture(file2);
end);
local file3 = filePath.."Settings-ArrowOption.png";
local file4 = filePath.."Settings-ArrowOption.png";
self.arrowOptionPool:ProcessAllObjects(function(widget)
widget:SetTexture(file3);
widget.barPool:ProcessAllObjects(function(bar)
bar:SetTexture(file4);
end);
end);
if self.hotkeyFramePool then
self.hotkeyFramePool:CallAllObjects("LoadTheme");
end
self.BackgroundDecor:SetTexture(filePath.."Settings-BackgroundDecor.png");
local themeID;
if ThemeUtil:IsDarkMode() then
themeID = 2;
self.BackgroundDecor:SetBlendMode("ADD");
else
themeID = 1;
self.BackgroundDecor:SetBlendMode("BLEND");
end
self.ScrollBar:SetTheme(themeID);
for i, button in ipairs(self.tabButtons) do
local isSelected = button.isSelected;
button.isSelected = true;
button:SetSelected(isSelected);
end
end
function DUIDialogSettingsMixin:UpdatePixel(scale)
if not scale then
scale = self:GetEffectiveScale();
end
local pixelOffset = 10.0;
local offset = API.GetPixelForScale(scale, pixelOffset);
self.BackgroundShadow:ClearAllPoints();
self.BackgroundShadow:SetPoint("TOPLEFT", self, "TOPLEFT", -offset, offset);
self.BackgroundShadow:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", offset, -offset);
--API.UpdateTextureSliceScale(self.Background);
--API.UpdateTextureSliceScale(self.BackgroundShadow);
end
function DUIDialogSettingsMixin:HighlightButton(button)
self.ButtonHighlight:Hide();
self.ButtonHighlight:ClearAllPoints();
if button and button:IsEnabled() then
self.ButtonHighlight:SetParent(button);
self.ButtonHighlight:SetPoint("TOPLEFT", button, "TOPLEFT", 0, 0);
self.ButtonHighlight:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", 0, 0);
self.ButtonHighlight:Show();
end
end
function DUIDialogSettingsMixin:OnHide()
self.focusedObject = nil;
self.focusedObjectOffsetY = nil;
self.scrollFrameTop = nil;
self.scrollFrameBottom = nil;
self:EnableGamePadButton(false);
self:UnregisterEvent("GAME_PAD_ACTIVE_CHANGED");
self:UnregisterEvent("GAME_PAD_DISCONNECTED");
addon.CallbackRegistry:Trigger("SettingsUI.Hide");
end
function DUIDialogSettingsMixin:OnEvent(event, ...)
if event == "GAME_PAD_ACTIVE_CHANGED" then
local isActive = ...
GAME_PAD_ACTIVE = isActive;
elseif event == "GAME_PAD_DISCONNECTED" then
GAME_PAD_ACTIVE = false;
end
end
function DUIDialogSettingsMixin:SetPreviewTexture(optionData)
if optionData.preview and (type(optionData.preview) == "string") then
self.Preview:SetTexture(PREVIEW_PATH..optionData.preview);
end
if optionData.ratio == 1 then
self.Preview:SetWidth(self.previewHeight);
elseif optionData.ratio == 2 then
self.Preview:SetWidth(2 * self.previewHeight);
else
end
end
function DUIDialogSettingsMixin:DisplayOptionInfo(optionData, choiceTooltip)
local hasPreview;
if optionData.preview then
hasPreview = true;
self:SetPreviewTexture(optionData);
else
hasPreview = false;
end
self.Preview:SetShown(hasPreview);
self.PreviewBorder:SetShown(hasPreview);
if hasPreview then
if not self.hasPreview then
self.hasPreview = true;
self.Description:ClearAllPoints();
self.Description:SetPoint("TOP", self.Preview, "BOTTOM", 0, -FRAME_PADDING);
end
else
if self.hasPreview then
self.hasPreview = nil;
self.Description:ClearAllPoints();
self.Description:SetPoint("TOP", self.Preview, "TOP", 0, -8);
end
end
if choiceTooltip and optionData.description then
self.Description:SetText(optionData.description.."\n\n"..choiceTooltip);
else
self.Description:SetText(optionData.description);
end
end
local function ValueTextFormatter_PrimaryControlKey(arrowOptionButton, dbValue)
local f = arrowOptionButton.HotkeyFrame;
if not f then
f = MainFrame.hotkeyFramePool:Acquire();
arrowOptionButton.HotkeyFrame = f;
end
f:SetBaseHeight(20);
local key, keyDesc, errorText;
if dbValue == 1 then
key = "SPACE";
keyDesc = L["Key Space"];
elseif dbValue == 2 then
key, errorText = API.GetBestInteractKey();
keyDesc = L["Key Interact"];
elseif dbValue == 0 then
key = "DISABLED";
keyDesc = L["Key Disabled"];
end
local fontString = arrowOptionButton.ValueText;
f:SetKey(key or "ERROR");
fontString:SetText(keyDesc);
local widgetWidth = f:GetWidth() + HOTKEYFRAME_VALUETEXT_GAP;
fontString:ClearAllPoints();
fontString:SetPoint("TOP", arrowOptionButton, "TOP", widgetWidth*0.5, ARROWOPTION_VALUETEXT_OFFSET_Y);
f:ClearAllPoints();
f:SetPoint("RIGHT", fontString, "LEFT", -HOTKEYFRAME_VALUETEXT_GAP, 0);
end
local function PrimaryControlKey_Interact_Tooltip()
local key, errorText = API.GetBestInteractKey();
if errorText then
local additionalTooltip = errorText.."\n\n"..L["Use Default Control Key Alert"];
return additionalTooltip
end
end
local function TTSHotkey_Tooltip()
local device;
if INPUT_DEVICE_ID == 1 then
device = "PC";
elseif INPUT_DEVICE_ID == 2 then
device = "Xbox";
elseif INPUT_DEVICE_ID == 3 then
device = "PlayStation";
elseif INPUT_DEVICE_ID == 4 then
device = "Switch";
else
device = "PC";
end
return L["TTS Use Hotkey Tooltip "..device]
end
local function QuestItemDisplay_Move_OnClick()
addon.QuestItemDisplay:EnterEditMode();
end
local function QuestItemDisplay_Reset_OnClick()
addon.QuestItemDisplay:ResetPosition();
end
local function QuestItemDisplayPosition_Validation()
local f = addon.QuestItemDisplay;
return f and f:IsUsingCustomPosition()
end
local function RPAddOn_Validation()
return addon.GetInstalledRPAddOnName() ~= nil
end
local function RPAddOn_ReplaceName_Tooltip()
local addOnName = addon.GetInstalledRPAddOnName();
if addOnName then
return L["Format Functionality Handled By"]:format(addOnName);
end
end
local Schematic = {
{
tabName = L["UI"],
options = {
{type = "ArrowOption", name = L["Theme"], description = L["Theme Desc"], dbKey = "Theme", preview = "Theme", ratio = 2,
choices = {
{dbValue = 1, valueText = L["Theme Brown"]},
{dbValue = 2, valueText = L["Theme Dark"]},
},
},
{type = "ArrowOption", name = L["Frame Size"], description = L["Frame Size Desc"], dbKey = "FrameSize",
choices = {
{dbValue = 0, valueText = L["Size Extra Small"]},
{dbValue = 1, valueText = L["Size Small"]},
{dbValue = 2, valueText = L["Size Medium"]},
{dbValue = 3, valueText = L["Size Large"]},
},
},
{type = "ArrowOption", name = L["Font Size"], description = L["Font Size Desc"], dbKey = "FontSizeBase", realignAfterClicks = true,
choices = {
{dbValue = 0, valueText = "10"},
{dbValue = 1, valueText = "12"},
{dbValue = 2, valueText = "14"},
{dbValue = 3, valueText = "16"},
},
},
{type = "Checkbox", name = L["Hide UI"], description = L["Hide UI Desc"], dbKey = "HideUI"},
{type = "Checkbox", name = L["Hide Unit Names"], description = L["Hide Unit Names Desc"], dbKey = "HideUnitNames", parentKey = "HideUI", requiredParentValue = true},
{type = "Checkbox", name = L["Show Copy Text Button"], description = L["Show Copy Text Button Desc"], preview = "CopyTextButton", ratio = 1, dbKey = "ShowCopyTextButton"},
{type = "Checkbox", name = L["Show NPC Name On Page"], description = L["Show NPC Name On Page Desc"], dbKey = "ShowNPCNameOnPage"},
{type = "Subheader", name = L["Quest"]},
{type = "Checkbox", name = L["Mark Highest Sell Price"], description = L["Mark Highest Sell Price Desc"], dbKey = "MarkHighestSellPrice", preview = "MarkHighestSellPrice", ratio = 1},
{type = "Checkbox", name = L["Show Quest Type Text"], description = L["Show Quest Type Text Desc"], dbKey = "QuestTypeText", preview = "QuestTypeText", ratio = 1},
{type = "Checkbox", name = L["Simplify Currency Rewards"], description = L["Simplify Currency Rewards Desc"], dbKey = "SimplifyCurrencyReward", preview = "SimplifyCurrencyReward", ratio = 2},
{type = "Subheader", name = L["Roleplaying"], validationFunc = RPAddOn_Validation},
{type = "Checkbox", name = L["Use RP Name In Dialogues"], description = L["Use RP Name In Dialogues Desc"], tooltip = RPAddOn_ReplaceName_Tooltip, dbKey = "UseRoleplayName", validationFunc = RPAddOn_Validation},
},
},
{
tabName = L["Camera"],
options = {
{type = "ArrowOption", name = L["Camera Movement"], dbKey="CameraMovement",
choices = {
{dbValue = 0, valueText = L["Camera Movement Off"]},
{dbValue = 1, valueText = L["Camera Movement Zoom In"]},
{dbValue = 2, valueText = L["Camera Movement Horizontal"]},
},
},
{type = "Checkbox", name = L["Change FOV"], description = L["Change FOV Desc"], dbKey = "CameraChangeFov", parentKey = "CameraMovement", requiredParentValue = 1, preview = "CameraChangeFov", ratio = 2},
{type = "Checkbox", name = L["Maintain Camera Position"], description = L["Maintain Camera Position Desc"], dbKey = "CameraMovement1MaintainPosition", parentKey = "CameraMovement", requiredParentValue = 1},
--{type = "Checkbox", name = L["Maintain Camera Position"], description = L["Maintain Camera Position Desc"], dbKey = "CameraMovement2MaintainPosition", parentKey = "CameraMovement", requiredParentValue = 2, },
{type = "Checkbox", name = L["Maintain Offset While Mounted"], description = L["Maintain Offset While Mounted Desc"], dbKey = "CameraMovementMountedCamera", parentKey = "CameraMovement", requiredParentValue = {1, 2}},
{type = "Checkbox", name = L["Disable Camera Movement Instance"], description = L["Disable Camera Movement Instance Desc"], dbKey = "CameraMovementDisableInstance", parentKey = "CameraMovement", requiredParentValue = {1, 2}},
},
},
{
tabName = L["Control"],
options = {
{type = "ArrowOption", name = L["Input Device"], dbKey = "InputDevice", description = L["Input Device Desc"],
choices = {
{dbValue = 1, valueText = L["Input Device KBM"]},
{dbValue = 2, valueText = L["Input Device Xbox"], tooltip = L["Input Device Xbox Tooltip"]},
{dbValue = 3, valueText = L["Input Device PlayStation"], tooltip = L["Input Device PlayStation Tooltip"]},
{dbValue = 4, valueText = L["Input Device Switch"], tooltip = L["Input Device Switch Tooltip"]},
},
},
{type = "ArrowOption", name = L["Primary Control Key"], description = L["Primary Control Key Desc"], dbKey = "PrimaryControlKey", valueTextFormatter = ValueTextFormatter_PrimaryControlKey, hasHotkey = true, parentKey = "InputDevice", requiredParentValue = 1,
choices = {
{dbValue = 1, valueText = L["Key Space"]},
{dbValue = 2, valueText = L["Key Interact"], tooltip = PrimaryControlKey_Interact_Tooltip},
{dbValue = 0, valueText = L["Key Disabled"], tooltip = L["Key Disabled Tooltip"]},
},
},
{type = "Subheader", name = L["Quest"]},
{type = "Checkbox", name = L["Press Button To Scroll Down"], description = L["Press Button To Scroll Down Desc"], dbKey = "ScrollDownThenAcceptQuest"},
},
},
{
tabName = L["Gameplay"],
options = {
{type = "Checkbox", name = L["Quest Item Display"], description = L["Quest Item Display Desc"], dbKey = "QuestItemDisplay", preview = "QuestItemDisplay", ratio = 2},
{type = "Checkbox", name = L["Quest Item Display Hide Seen"], description = L["Quest Item Display Hide Seen Desc"], dbKey = "QuestItemDisplayHideSeen", parentKey = "QuestItemDisplay", requiredParentValue = true},
{type = "Custom", name = L["Move Position"], icon = "Settings-Move.png", parentKey = "QuestItemDisplay", requiredParentValue = true, onClickFunc = QuestItemDisplay_Move_OnClick},
{type = "Custom", name = L["Reset Position"], icon = "Settings-Reset.png", description = L["Quest Item Display Reset Position Desc"], parentKey = "QuestItemDisplay", requiredParentValue = true, validationFunc = QuestItemDisplayPosition_Validation, onClickFunc = QuestItemDisplay_Reset_OnClick},
{type = "Subheader", name = L["Gossip"]},
{type = "Checkbox", name = L["Auto Select Gossip"], description = L["Auto Select Gossip Desc"], dbKey = "AutoSelectGossip"},
{type = "Checkbox", name = L["Force Gossip"], description = L["Force Gossip Desc"], dbKey = "ForceGossip"},
--{type = "Checkbox", name = L["Nameplate Dialog"], description = L["Nameplate Dialog Desc"], dbKey = "NameplateDialogEnabled", preview = "NameplateDialogEnabled", ratio = 1},
},
},
{
tabName = L["Accessibility"],
options = {
{type = "Checkbox", name = L["TTS"], description = L["TTS Desc"], dbKey = "TTSEnabled", preview = "TTSButton", ratio = 1},
{type = "Checkbox", name = L["TTS Use Hotkey"], description = L["TTS Use Hotkey Desc"], tooltip = TTSHotkey_Tooltip, dbKey = "TTSUseHotkey", parentKey = "TTSEnabled", requiredParentValue = true},
{type = "Checkbox", name = L["TTS Auto Play"], description = L["TTS Auto Play Desc"], dbKey = "TTSAutoPlay", parentKey = "TTSEnabled", requiredParentValue = true},
{type = "Checkbox", name = L["TTS Auto Stop"], description = L["TTS Auto Stop Desc"], dbKey = "TTSAutoStop", parentKey = "TTSEnabled", requiredParentValue = true},
},
},
};
local CloseButtonScripts = {};
function CloseButtonScripts:OnClick()
MainFrame:Hide();
end
function CloseButtonScripts:OnEnter()
self.Highlight:Show();
end
function CloseButtonScripts:OnLeave()
self.Highlight:Hide();
end
function CloseButtonScripts:OnMouseDown()
self.Icon:SetPoint("CENTER", 0, -1);
end
function CloseButtonScripts:OnMouseUp()
self.Icon:SetPoint("CENTER", 0, 0);
end
function CloseButtonScripts:OnHide()
self.Highlight:Hide();
self.Icon:SetPoint("CENTER", 0, 0);
end
local function RemoveWidget(widget)
widget:Hide();
widget:ClearAllPoints();
widget:SetParent(MainFrame);
widget.HotkeyFrame = nil;
end
local function CreateOptionButton()
local optionButton = CreateFrame("Button", nil, MainFrame, "DUIDialogSettingsOptionTemplate");
return optionButton
end
local function CreateCheckbox()
local checkbox = CreateFrame("Button", nil, MainFrame, "DUIDialogSettingsCheckboxTemplate");
return checkbox
end
local function OnAcquireCheckbox(checkbox)
checkbox:SetTexture(ThemeUtil:GetTextureFile("Settings-Checkbox.png"));
end
local function CreateArrowOption()
local widget = CreateFrame("Frame", nil, MainFrame, "DUIDialogSettingsArrowOptionTemplate");
return widget
end
local function OnAcquireArrowOption(widget)
widget:SetTexture(ThemeUtil:GetTextureFile("Settings-ArrowOption.png"));
end
local TextureFrameMixin = {};
function TextureFrameMixin:SetTexture(file)
self.Texture:SetTexture(file);
end
function TextureFrameMixin:SetVertexColor(r, g, b, a)
self.Texture:SetVertexColor(r, g, b, a)
end
local function CreateTexture()
local f = CreateFrame("Frame", nil, MainFrame, "DUIDialogSettingsTextureFrameTemplate");
API.Mixin(f, TextureFrameMixin);
return f
end
local ScrollFrameMixin = {};
function ScrollFrameMixin:SetViewSize(height)
self.viewSize = height;
self:SetHeight(height);
end
function ScrollFrameMixin:GetViewSize()
return self.viewSize or 0
end
function ScrollFrameMixin:SetScrollRange(range)
if range < 0 then
range = 0;
self.scrollBar:Hide();
MainFrame.VerticalDivider:Show();
else
self.scrollBar:Show();
MainFrame.VerticalDivider:Hide();
end
self.maxScrollOffset = range;
self.scrollBar:UpdateThumbSize();
end
function ScrollFrameMixin:GetScrollRange()
return self.maxScrollOffset or 0
end
function ScrollFrameMixin:SetContentHeight(contentHeight)
self:SetScrollRange(contentHeight - self:GetViewSize());
end
function ScrollFrameMixin:GetScrollOffset()
return self.scrollOffset or 0
end
function ScrollFrameMixin:SetScrollOffset(scrollOffset)
scrollOffset = Clamp(scrollOffset, 0, self.maxScrollOffset);
if scrollOffset ~= self.scrollOffset then
self.scrollOffset = scrollOffset;
self.Reference:SetPoint("TOPLEFT", 0, scrollOffset);
self.scrollBar:UpdateThumbPosition();
end
end
function ScrollFrameMixin:IsAtBottom()
return self:GetScrollOffset() + 0.1 >= self:GetScrollRange();
end
function ScrollFrameMixin:ScrollBy(offset)
self:SetScrollOffset( self:GetScrollOffset() + offset);
end
function ScrollFrameMixin:ScrollToBottom()
self:SetScrollOffset(self:GetScrollRange());
end
function ScrollFrameMixin:OnMouseWheel(delta)
if delta > 0 then
self:ScrollBy(-OPTIONBUTTON_HEIGHT);
else
self:ScrollBy(OPTIONBUTTON_HEIGHT);
end
end
function DUIDialogSettingsMixin:Init()
--Tab Buttons
if not self.tabButtons then
self.tabButtons = {};
end
self.optionButtonPool = API.CreateObjectPool(CreateOptionButton, RemoveWidget);
self.checkboxPool = API.CreateObjectPool(CreateCheckbox, RemoveWidget, OnAcquireCheckbox);
self.arrowOptionPool = API.CreateObjectPool(CreateArrowOption, RemoveWidget, OnAcquireArrowOption);
self.texturePool = API.CreateObjectPool(CreateTexture);
local function CreateHotkeyFrame()
local f = CreateFrame("Frame", nil, self, "DUIDialogHotkeyTemplate");
f:SetShowDisabledKey(true);
return f
end
local function RemoveHotkeyFrame(f)
f:ClearKey();
f:ClearAllPoints();
f:SetParent(self);
end
self.hotkeyFramePool = API.CreateObjectPool(CreateHotkeyFrame, RemoveHotkeyFrame);
self.numTabs = #Schematic;
for i, tabData in ipairs(Schematic) do
if not self.tabButtons[i] then
self.tabButtons[i] = CreateFrame("Button", nil, self.Header.Container, "DUIDialogSettingsTabButtonTemplate");
SetupRepositionObject(self.tabButtons[i]);
end
self.tabButtons[i].tabID = i;
self.tabButtons[i]:SetName(tabData.tabName);
end
--Close Button
local CloseButton = self.Header.CloseButton;
for method, func in pairs(CloseButtonScripts) do
CloseButton:SetScript(method, func);
end
CloseButton.Background:SetTexCoord(0, 0.5, 0, 0.5);
CloseButton.Highlight:SetTexCoord(0.5, 1, 0, 0.5);
CloseButton.Icon:SetTexCoord(0.0625, 0.1875, 0.625, 0.875);
API.Mixin(self.ScrollFrame, ScrollFrameMixin);
self.ScrollFrame:SetScript("OnMouseWheel", ScrollFrameMixin.OnMouseWheel);
--ScrollBar
local ScrollBar = addon.CreateScrollBar(self);
self.ScrollBar = ScrollBar;
self.ScrollFrame.scrollBar = ScrollBar;
ScrollBar:SetOwner(self.ScrollFrame);
ScrollBar:SetAlwaysVisible(false);
ScrollBar:ShowScrollToBottomButton(false);
ScrollBar:Show();
self.Init = nil;
self:LoadTheme();
end
function DUIDialogSettingsMixin:Layout()
OPTIONBUTTON_HEIGHT = FONT_HEIGHT_NORMAL + 2*BUTTON_PADDING_LARGE;
--Header
local tabButtonHeight = FONT_HEIGHT_LARGE + 2*BUTTON_PADDING_LARGE;
local minTabButtonWidth = 2 * tabButtonHeight;
local headerHeight = tabButtonHeight;
self.Header:ClearAllPoints();
self.Header:SetPoint("TOPLEFT", self, "TOPLEFT", FRAME_PADDING, -FRAME_PADDING);
self.Header:SetPoint("TOPRIGHT", self, "TOPRIGHT", -FRAME_PADDING, -FRAME_PADDING);
self.Header:SetHeight(headerHeight);
local tabButtonContainer = self.Header.Container;
self.Header.CloseButton:ClearAllPoints();
self.Header.CloseButton:SetParent(tabButtonContainer);
self.Header.CloseButton:SetPoint("RIGHT", tabButtonContainer, "RIGHT", 0, 0);
self.Header.CloseButton:SetSize(minTabButtonWidth, tabButtonHeight);
self.Header.CloseButton.Icon:SetSize(FONT_HEIGHT_LARGE, FONT_HEIGHT_LARGE);
self.HeaderDivider:ClearAllPoints();
self.HeaderDivider:SetPoint("TOPLEFT", self.Header, "BOTTOMLEFT", 0, -TAB_BUTTON_GAP);
self.HeaderDivider:SetPoint("TOPRIGHT", self.Header, "BOTTOMRIGHT", 0, -TAB_BUTTON_GAP);
self.HeaderDivider:SetHeight(9);
--Tab Buttons
local buttonWidth;
local tabButtonsSpan = 0;
for i, button in ipairs(self.tabButtons) do
buttonWidth = API.Round(button.Name:GetWrappedWidth() + 2*FONT_HEIGHT_LARGE);
if buttonWidth < minTabButtonWidth then
buttonWidth = minTabButtonWidth;
end
button:SetSize(buttonWidth, tabButtonHeight);
tabButtonsSpan = tabButtonsSpan + buttonWidth;
button:ClearAllPoints();
if i > 1 then
button:SetPoint("LEFT", self.tabButtons[i - 1], "RIGHT", TAB_BUTTON_GAP, 0);
tabButtonsSpan = tabButtonsSpan + TAB_BUTTON_GAP;
end
end
local tabFromOffsetX = (INPUT_DEVICE_GAME_PAD and 60) or 0;
local firstTabButton = self.tabButtons[1];
firstTabButton:ClearAllPoints();
firstTabButton:SetPoint("LEFT", tabButtonContainer, "LEFT", tabFromOffsetX, 0);
--ScrollFrame
local scrollFrameWidth = OPTIONBUTTON_WIDTH;
local scrollFrameHeight = NUM_VISIBLE_OPTIONS * OPTIONBUTTON_HEIGHT;
local ScrollFrame = self.ScrollFrame;
local gapToHeader = 12;
ScrollFrame:ClearAllPoints();
ScrollFrame:SetPoint("TOPLEFT", self.Header, "BOTTOMLEFT", 0, -gapToHeader);
ScrollFrame:SetWidth(scrollFrameWidth);
ScrollFrame:SetViewSize(scrollFrameHeight);
--ScrollBar
local ScrollBar = self.ScrollBar;
local scrollBarOffsetX = OPTIONBUTTON_FROM_Y;
ScrollBar:SetPoint("TOPLEFT", ScrollFrame, "TOPRIGHT", scrollBarOffsetX, 0);
ScrollBar:SetPoint("BOTTOMLEFT", ScrollFrame, "BOTTOMRIGHT", scrollBarOffsetX, 0);
ScrollBar:OnSizeChanged();
self.VerticalDivider:ClearAllPoints();
self.VerticalDivider:SetPoint("TOPLEFT", ScrollBar, "TOP", -2, 0);
self.VerticalDivider:SetPoint("BOTTOMLEFT", ScrollBar, "BOTTOM", -2, 0);
local frameWidth = API.Round((scrollFrameWidth + 1.5*FRAME_PADDING) / 0.618);
local frameHeight = FRAME_PADDING + headerHeight + gapToHeader + scrollFrameHeight + FRAME_PADDING;
local rightAreaWidth = API.Round(frameWidth - scrollFrameWidth - 2*FRAME_PADDING);
local descriptionWidth = API.Round(frameWidth - scrollFrameWidth - 3*FRAME_PADDING -BUTTON_PADDING_LARGE);
local previewShrink = 1;
self.Preview:ClearAllPoints();
self.Preview:SetPoint("TOP", self, "TOPRIGHT", -rightAreaWidth*0.5 -previewShrink, -(headerHeight + 2.5*FRAME_PADDING));
local previewWidth = descriptionWidth - 2*previewShrink;
local previewHeight = 0.5*previewWidth;
self.Preview:SetSize(previewWidth, 0.5*previewWidth);
self.previewHeight = previewHeight;
self.Description:SetWidth(descriptionWidth);
self.Description:ClearAllPoints();
self.Description:SetPoint("TOP", self.Preview, "TOP", 0, -8);
self:SetSize(frameWidth, frameHeight);
--self.BackgroundGradient:SetWidth(frameHeight);
self.BackgroundDecor:SetSize(rightAreaWidth, rightAreaWidth);
self.DecorMask:SetSize(rightAreaWidth, rightAreaWidth);
self.DecorMask:ClearAllPoints();
self.DecorMask:SetPoint("BOTTOM", self.Description, "BOTTOM", 0, -16);
--Reduce tab button size if necessary
local headerObjectWidth = tabButtonsSpan + minTabButtonWidth + TAB_BUTTON_GAP;
if INPUT_DEVICE_GAME_PAD then
headerObjectWidth = headerObjectWidth + tabFromOffsetX + 4 * TAB_BUTTON_GAP + minTabButtonWidth;
end
local headerWidth = frameWidth - 2*FRAME_PADDING;
if headerObjectWidth > headerWidth then
if headerObjectWidth * 0.8 < headerWidth then
tabButtonContainer:SetScale(0.8);
else
tabButtonContainer:SetScale(0.6);
end
else
tabButtonContainer:SetScale(1);
end
end
function DUIDialogSettingsMixin:SelectTabByID(tabID, forceUpdate)
if tabID == self.tabID and not forceUpdate then return false end;
if self.tabID then --Save Scroll Position
self["tabOffset"..self.tabID] = self.ScrollFrame:GetScrollOffset();
self["tab"..self.tabID.."gamepadFocusIndex"] = self.gamepadFocusIndex;
end
self.tabID = tabID;
--Update Options
self.optionButtonPool:Release();
self.checkboxPool:Release();
self.arrowOptionPool:Release();
self.texturePool:Release();
self.hotkeyFramePool:Release();
self:ResetGamePadObjects();
--Highlight Button
self.Header.Selection:ClearAllPoints();
self.Header.Selection:Hide();
for i, button in ipairs(self.tabButtons) do
if button.tabID == tabID then
button:SetSelected(true);
self.Header.Selection:SetPoint("TOPLEFT", button, "TOPLEFT", 0, 0);
self.Header.Selection:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", 0, 0);
self.Header.Selection:Show();
else
button:SetSelected(false);
end
end
if INPUT_DEVICE_GAME_PAD then
local gap = 4 * TAB_BUTTON_GAP;
local lb = self.hotkeyFramePool:Acquire();
lb:SetKey("PADLSHOULDER");
lb:SetPoint("LEFT", self.Header.Container, "LEFT", 0, 0);
local firstTabButton = self.tabButtons[1];
firstTabButton:ClearAllPoints();
firstTabButton:SetPoint("LEFT", lb, "RIGHT", gap, 0);
local rb = self.hotkeyFramePool:Acquire();
rb:SetKey("PADRSHOULDER");
rb:SetPoint("LEFT", self.tabButtons[ #self.tabButtons ], "RIGHT", gap, 0);
end
local tabData = Schematic[tabID];
local optionButton;
local numShownOptions = 0;
local isOptionValid;
local dbKeyToWidget = {};
for i, optionData in ipairs(tabData.options) do
if optionData.parentKey then
isOptionValid = false;
local requirement = optionData.requiredParentValue;
local dbValue = GetDBValue(optionData.parentKey);
if type(requirement) == "table" then
for _, requiredParentValue in ipairs(requirement) do
if dbValue == requiredParentValue then
isOptionValid = true;
break
end
end
else
if dbValue == optionData.requiredParentValue then
isOptionValid = true;
end
end
if dbKeyToWidget[optionData.parentKey] then
dbKeyToWidget[optionData.parentKey].isParentOption = true;
end
else
isOptionValid = true;
end
if isOptionValid and optionData.validationFunc then
isOptionValid = optionData.validationFunc();
end
if isOptionValid then
numShownOptions = numShownOptions + 1;
optionButton = self.optionButtonPool:Acquire();
optionButton.isParentOption = nil;
optionButton:SetParent(self.ScrollFrame);
optionButton:SetData(optionData);
optionButton:SetSize(OPTIONBUTTON_WIDTH, OPTIONBUTTON_HEIGHT);
optionButton:SetPoint("TOPLEFT", self.ScrollFrame.Reference, "TOPLEFT", 0, (1 - numShownOptions)*OPTIONBUTTON_HEIGHT);
if optionData.dbKey then
dbKeyToWidget[optionData.dbKey] = optionButton;
end
end
end
self.ScrollFrame:SetContentHeight(numShownOptions * OPTIONBUTTON_HEIGHT);
self.ScrollFrame:SetScrollOffset(self["tabOffset"..self.tabID] or 0);
self.dbKeyToWidget = dbKeyToWidget;
if GAME_PAD_ACTIVE then
self:FocusObjectByIndex(self["tab"..self.tabID.."gamepadFocusIndex"] or 1);
end
end
function DUIDialogSettingsMixin:SelectTabByDelta(delta)
local tabID = self.tabID or 0;
if delta > 0 and tabID < self.numTabs then
self:SelectTabByID(tabID + 1);
elseif delta < 0 and tabID > 1 then
self:SelectTabByID(tabID - 1);
end
end
function DUIDialogSettingsMixin:UpdateCurrentTab()
self:SelectTabByID(self.tabID, true)
end
function DUIDialogSettingsMixin:RequestUpdate()
if self:IsVisible() then
self:UpdateCurrentTab();
end
end
function DUIDialogSettingsMixin:SetFocusedObject(object)
self.focusedObject = object;
if object then
local _;
_, self.focusedObjectOffsetY = object:GetCenter();
else
self.focusedObjectOffsetY = nil;
end
end
function DUIDialogSettingsMixin:ReAlignToFocusedObject()
--The UI's dimension change with Font Size, so we need maintain the option's offsetY so players don't click another option by accident
if self.focusedObject and self.focusedObject:IsShown() and self.focusedObjectOffsetY then
local _, newOffsetY = self.focusedObject:GetCenter();
local point, relativeTo, relativePoint, offsetX, offsetY = self:GetPoint(1);
self:ClearAllPoints();
self:SetPoint(point, relativeTo, relativePoint, offsetX, offsetY + self.focusedObjectOffsetY - newOffsetY);
self:UpdateScrollFrameBound();
end
end
function DUIDialogSettingsMixin:ToggleUI()
self:SetShown(not self:IsShown());
end
DUIDialogSettingsTabButtonMixin = {};
function DUIDialogSettingsTabButtonMixin:OnEnter()
MainFrame:HighlightButton(self);
end
function DUIDialogSettingsTabButtonMixin:OnLeave()
MainFrame:HighlightButton(nil);
end
function DUIDialogSettingsTabButtonMixin:OnMouseDown(button)
if button ~= "LeftButton" or self.isSelected then return end;
self.Name:SetPoint("CENTER", 0, -1);
end
function DUIDialogSettingsTabButtonMixin:OnMouseUp()
self.Name:SetPoint("CENTER", 0, 0);
end
function DUIDialogSettingsTabButtonMixin:OnClick()
MainFrame:SelectTabByID(self.tabID);
end
function DUIDialogSettingsTabButtonMixin:SetName(name)
self.Name:SetText(string.upper(name));
end
function DUIDialogSettingsTabButtonMixin:SetSelected(state)
if state then
self.isSelected = true;
self.Name:SetFontObject("DUIFont_Quest_Quest");
else
if self.isSelected then
self.isSelected = nil;
self.Name:SetFontObject("DUIFont_Quest_Gossip");
end
end
end
DUIDialogSettingsOptionMixin = {};
function DUIDialogSettingsOptionMixin:OnEnter()
local choiceTooltip;
if not self.isSubheader then
MainFrame:HighlightButton(self);
MainFrame:SetGamePadFocus(self);
if self.widget then
choiceTooltip = self.widget:GetSelectedChoiceTooltip();
end
end
MainFrame:DisplayOptionInfo(self.optionData, choiceTooltip);
end
function DUIDialogSettingsOptionMixin:OnLeave()
if not self:IsMouseOver() then
MainFrame:HighlightButton(nil);
end
end
function DUIDialogSettingsOptionMixin:OnClick(button)
MainFrame:SetFocusedObject(self);
if self.widget and self.widget.OnClick and self.widget:IsEnabled() then
self.widget:OnClick(button);
elseif self.optionData.onClickFunc then
self.optionData.onClickFunc(self);
end
MainFrame:HighlightButton(nil);
self:OnEnter();
end
function DUIDialogSettingsOptionMixin:SetCheckbox(optionData)
self.widget = MainFrame.checkboxPool:Acquire();
self.widget:SetParent(self);
self.widget:SetPoint("RIGHT", self, "RIGHT", -BUTTON_PADDING_LARGE, 0);
self.widget:SetWidgetHeight(OPTION_WIDGET_SIZE);
self.widget:SetChecked(GetDBValue(self.dbKey) == true);
end
function DUIDialogSettingsOptionMixin:SetArrowOption(optionData)
self.widget = MainFrame.arrowOptionPool:Acquire();
self.widget:SetParent(self);
self.widget:SetPoint("RIGHT", self, "RIGHT", -BUTTON_PADDING_LARGE, 0);
self.widget:SetWidgetHeight(OPTION_WIDGET_SIZE);
self.widget:SetData(optionData);
end
function DUIDialogSettingsOptionMixin:SetCustomButton(optionData)
self.widget = nil;
end
function DUIDialogSettingsOptionMixin:SetSubheader()
--[[
local icon = MainFrame.texturePool:Acquire();
icon:SetSize(FONT_HEIGHT_NORMAL, FONT_HEIGHT_NORMAL);
icon:SetTexture(FILE_PATH.."Settings-SubheaderIcon.png");
icon:SetVertexColor(0.50, 0.36, 0.24);
icon:SetPoint("LEFT", self, "LEFT", 4, 0);
icon:SetParent(self);
--]]
end
function DUIDialogSettingsOptionMixin:SetData(optionData)
self.optionData = optionData;
self.dbKey = optionData.dbKey;
self.updateTabAfterClicks = optionData.updateTabAfterClicks;
local isSubheader;
if optionData.type == "Subheader" then
isSubheader = true;
self:SetSubheader();
elseif optionData.type == "Checkbox" then
self:SetCheckbox(optionData);
elseif optionData.type == "ArrowOption" then
self:SetArrowOption(optionData);
elseif optionData.type == "Custom" then
self:SetCustomButton(optionData);
end
self.widgetType = optionData.type;
if isSubheader then
self.Label:SetText(string.upper(optionData.name));
if not self.isSubheader then
self.Label:SetFontObject("DUIFont_Settings_Disabled");
end
else
self.Label:SetText(optionData.name);
if self.isSubheader then
self.Label:SetFontObject("DUIFont_Quest_Paragraph");
end
MainFrame:IndexGamePadObject(self);
end
self.isSubheader = isSubheader;
local nameOffset;
if optionData.parentKey then
nameOffset = OPTIONBUTTON_LABEL_OFFSET + 24;
local branch = MainFrame.texturePool:Acquire();
branch:SetSize(OPTIONBUTTON_HEIGHT*0.5, OPTIONBUTTON_HEIGHT*0.5);
branch:SetTexture(ThemeUtil:GetTextureFile("Settings-SubOptionIcon.png"));
branch:SetVertexColor(1, 1, 1, 0.5);
branch:SetPoint("BOTTOM", self, "LEFT", OPTIONBUTTON_LABEL_OFFSET + 2, 0);
branch:SetParent(self);
else
nameOffset = OPTIONBUTTON_LABEL_OFFSET;
end
if optionData.icon then
local icon = MainFrame.texturePool:Acquire();
local iconSize = OPTION_WIDGET_SIZE;
local iconOffset = -0.125*iconSize;
icon:SetSize(iconSize, iconSize);
icon:SetTexture(ThemeUtil:GetTextureFile(optionData.icon));
icon:SetVertexColor(1, 1, 1, 1);
icon:SetPoint("LEFT", self, "LEFT", nameOffset + iconOffset, 0);
icon:SetParent(self);
nameOffset = nameOffset + iconSize;
end
self.Label:ClearAllPoints();
self.Label:SetPoint("LEFT", self, "LEFT", nameOffset, 0);
end
DUIDialogSettingsArrowOptionMixin = {};
local function ArrowButton_OnClick(self)
self:GetParent():SelectChoiceByDelta(self.delta);
end
local function ArrowButton_OnEnter(self)
self:GetParent():GetParent():OnEnter();
end
local function ArrowButton_OnLeave(self)
self:GetParent():GetParent():OnLeave();
end
local function ArrowButton_OnMouseDown(self)
if not self:IsEnabled() then return end;
if self.delta < 0 then
self.Texture:SetPoint("CENTER", -1, 0);
else
self.Texture:SetPoint("CENTER", 1, 0);
end
end
local function ArrowButton_OnMouseUp(self)
self.Texture:SetPoint("CENTER", 0, 0);
end
local function ArrowButton_OnEnable(self)
self:SetAlpha(1);
end
local function ArrowButton_OnDisable(self)
self:SetAlpha(DISABLED_TEXTURE_ALPHA);
end
local function RemoveBar(bar)
bar:Hide();
bar:ClearAllPoints();
end
local function OnAcquireBar(bar)
bar:SetTexture(ThemeUtil:GetTextureFile("Settings-ArrowOption.png"));
end
function DUIDialogSettingsArrowOptionMixin:OnLoad()
self.ValueText:SetPoint("TOP", self, "TOP", 0, ARROWOPTION_VALUETEXT_OFFSET_Y);
self.LeftArrow.delta = -1;
self.LeftArrow:SetScript("OnEnter", ArrowButton_OnEnter);
self.LeftArrow:SetScript("OnLeave", ArrowButton_OnLeave);
self.LeftArrow:SetScript("OnClick", ArrowButton_OnClick);
self.LeftArrow:SetScript("OnMouseDown", ArrowButton_OnMouseDown);
self.LeftArrow:SetScript("OnMouseUp", ArrowButton_OnMouseUp);
self.LeftArrow:SetScript("OnEnable", ArrowButton_OnEnable);
self.LeftArrow:SetScript("OnDisable", ArrowButton_OnDisable);
self.RightArrow.delta = 1;
self.RightArrow:SetScript("OnEnter", ArrowButton_OnEnter);
self.RightArrow:SetScript("OnLeave", ArrowButton_OnLeave);
self.RightArrow:SetScript("OnClick", ArrowButton_OnClick);
self.RightArrow:SetScript("OnMouseDown", ArrowButton_OnMouseDown);
self.RightArrow:SetScript("OnMouseUp", ArrowButton_OnMouseUp);
self.RightArrow:SetScript("OnEnable", ArrowButton_OnEnable);
self.RightArrow:SetScript("OnDisable", ArrowButton_OnDisable);
local function CreateBar()
local bar = self:CreateTexture(nil, "OVERLAY");
bar:SetTextureSliceMargins(1, 1, 1, 1);
bar:SetTextureSliceMode(1);
bar:SetTexCoord(0, 16/128, 124/128, 1);
return bar
end
self.barPool = API.CreateObjectPool(CreateBar, RemoveBar, OnAcquireBar);
end
function DUIDialogSettingsArrowOptionMixin:SetNumChoices(numChoices, forceUpdate)
if numChoices ~= self.numChoices or forceUpdate then
self.barPool:Release();
self.numChoices = numChoices;
self.bars = {};
local barHeight = API.GetPixelForWidget(self, ARROWOTPION_BAR_HEIGHT);
local gap = API.GetPixelForWidget(self, 4);
local buttonWidth = self.LeftArrow:GetWidth();
local barShrink = 4;
local fromOffsetX = buttonWidth + barShrink;
local barWidth = (self:GetWidth() -2*barShrink - 2*buttonWidth - (numChoices - 1)*gap) / numChoices;
local bar;
for i = 1, numChoices do
bar = self.barPool:Acquire();
bar:SetSize(barWidth, barHeight);
bar:SetPoint("BOTTOMLEFT", self, "BOTTOMLEFT", fromOffsetX + (gap + barWidth) * (i - 1), 2);
self.bars[i] = bar;
end
end
end
function DUIDialogSettingsArrowOptionMixin:GetCentralWidth()
return self:GetWidth() - 2*self.LeftArrow:GetWidth();
end
function DUIDialogSettingsArrowOptionMixin:SetWidgetWidth(width)
local centralWidth = self:GetCentralWidth();
end
function DUIDialogSettingsArrowOptionMixin:SetWidgetHeight(height)
self.LeftArrow.Texture:SetSize(height, height);
self.RightArrow.Texture:SetSize(height, height);
self:SetHeight(height);
self:SetWidth(height * ARROWOTPION_WIDTH_RATIO);
end
function DUIDialogSettingsArrowOptionMixin:SetValueTextByID(id)
if self.valueTextFormatter then
self.valueTextFormatter(self, self.choices[id].dbValue);
else
local valueText = self.choices[id].valueText;
self.ValueText:SetText(valueText);
end
end
function DUIDialogSettingsArrowOptionMixin:SelectChoiceByID(id)
if not self.choices[id] then
id = 1;
end
local choiceData = self.choices[id];
if choiceData then
self:SetValueTextByID(id);
end
self.selectedID = id;
for i, bar in ipairs(self.bars) do
if i == id then
bar:SetAlpha(1);
else
bar:SetAlpha(DISABLED_TEXTURE_ALPHA);
end
end
self.LeftArrow:SetEnabled(id ~= 1);
self.RightArrow:SetEnabled(id ~= self.numChoices);
end
function DUIDialogSettingsArrowOptionMixin:SelectNextChoice()
if ARROWOTPION_CYCLING then
self.selectedID = self.selectedID + 1;
if self.selectedID > self.numChoices then
self.selectedID = 1;
end
else
if self.selectedID < self.numChoices then
self.selectedID = self.selectedID + 1;
else
return false
end
end
self:SelectChoiceByID(self.selectedID);
return true
end
function DUIDialogSettingsArrowOptionMixin:SelectPreviousChoice()
if ARROWOTPION_CYCLING then
self.selectedID = self.selectedID - 1;
if self.selectedID < 1 then
self.selectedID = self.numChoices;
end
else
if self.selectedID > 1 then
self.selectedID = self.selectedID - 1;
else
return false
end
end
self:SelectChoiceByID(self.selectedID);
return true
end
function DUIDialogSettingsArrowOptionMixin:SelectChoiceByDelta(delta)
--right = 1, left = -1
local anyChange;
if delta > 0 then
anyChange = self:SelectNextChoice();
else
anyChange = self:SelectPreviousChoice();
end
if anyChange then
self:PostClick();
end
end
function DUIDialogSettingsArrowOptionMixin:PostClick()
local optionButton = self:GetParent();
MainFrame:SetFocusedObject(optionButton);
local value = self.choices[self.selectedID].dbValue;
SetDBValue(optionButton.dbKey, value);
if optionButton.isParentOption or optionButton.updateTabAfterClicks then
MainFrame:UpdateCurrentTab();
end
if self.realignAfterClicks then
MainFrame:ReAlignToFocusedObject();
end
self:GetParent():OnEnter();
end
function DUIDialogSettingsArrowOptionMixin:SetData(optionData)
self.choices = optionData.choices;
self.dbKey = optionData.dbKey;
self.valueTextFormatter = optionData.valueTextFormatter;
self.realignAfterClicks = optionData.realignAfterClicks;
self:SetNumChoices(#self.choices);
if not optionData.hasHotkey then
self.ValueText:ClearAllPoints();
self.ValueText:SetPoint("TOP", self, "TOP", 0, ARROWOPTION_VALUETEXT_OFFSET_Y);
end
local selectedID = 1;
local dbValue = GetDBValue(self.dbKey);
for id, choiceData in ipairs(self.choices) do
if dbValue == choiceData.dbValue then
selectedID = id;
break
end
end
self:SelectChoiceByID(selectedID);
end
function DUIDialogSettingsArrowOptionMixin:SetTexture(file)
self.LeftArrow.Texture:SetTexture(file);
self.LeftArrow.Highlight:SetTexture(file);
self.RightArrow.Texture:SetTexture(file);
self.RightArrow.Highlight:SetTexture(file);
end
function DUIDialogSettingsArrowOptionMixin:GetSelectedChoiceTooltip()
if self.selectedID and self.choices and self.choices[self.selectedID] then
local tooltip = self.choices[self.selectedID].tooltip;
if type(tooltip) == "function" then
return tooltip()
else
return tooltip
end
end
end
DUIDialogSettingsCheckboxMixin = {};
function DUIDialogSettingsCheckboxMixin:OnEnter()
self:GetParent():OnEnter();
end
function DUIDialogSettingsCheckboxMixin:OnLeave()
self:GetParent():OnLeave();
end
function DUIDialogSettingsCheckboxMixin:SetTexture(file)
self.Background:SetTexture(file);
self.Check:SetTexture(file);
end
function DUIDialogSettingsCheckboxMixin:OnClick()
self:Toggle();
local optionButton = self:GetParent();
SetDBValue(optionButton.dbKey, self.checked);
if optionButton.isParentOption or optionButton.updateTabAfterClicks then
MainFrame:UpdateCurrentTab();
end
self:OnEnter();
end
function DUIDialogSettingsCheckboxMixin:SetChecked(state)
self.checked = state;
self.Check:SetShown(state);
if state then
self.Background:SetTexCoord(0.5, 1, 0, 0.5);
else
self.Background:SetTexCoord(0, 0.5, 0, 0.5);
end
end
function DUIDialogSettingsCheckboxMixin:GetChecked()
return self.checked == true
end
function DUIDialogSettingsCheckboxMixin:Toggle()
self.checked = not self.checked;
self:SetChecked(self.checked);
end
function DUIDialogSettingsCheckboxMixin:SetWidgetHeight(height)
self:SetSize(height, height);
self.Check:SetSize(height*0.5, height*0.5);
end
function DUIDialogSettingsCheckboxMixin:GetSelectedChoiceTooltip()
local optionButton = self:GetParent();
local tooltip = optionButton.optionData and optionButton.optionData.tooltip;
if tooltip then
if type(tooltip) == "function" then
return tooltip(self.checked)
else
return tooltip
end
end
end
do --GamePad/Controller
function DUIDialogSettingsMixin:ResetGamePadObjects()
self.gamepadMaxIndex = 0;
self.gamepadFocusIndex = nil;
self.gamepadFocus = nil;
self.gamepadObjects = {};
end
function DUIDialogSettingsMixin:IndexGamePadObject(object)
self.gamepadMaxIndex = self.gamepadMaxIndex + 1;
self.gamepadObjects[self.gamepadMaxIndex] = object;
object.gamepadIndex = self.gamepadMaxIndex;
end
function DUIDialogSettingsMixin:ClearGamePadFocus()
if self.gamepadFocus then
--self.gamepadFocus:OnLeave();
self.gamepadFocus = nil;
end
end
function DUIDialogSettingsMixin:SetGamePadFocus(optionButton)
self.gamepadFocusIndex = optionButton.gamepadIndex;
self.gamepadFocus = optionButton;
end
function DUIDialogSettingsMixin:FocusObjectByIndex(index)
local object = self.gamepadObjects[index];
if object then
self.gamepadFocusIndex = index;
self.gamepadFocus = object;
self.gamepadFocus:OnEnter();
return true
end
end
function DUIDialogSettingsMixin:FocusObjectByDelta(delta)
local maxIndex = self.gamepadMaxIndex or 0;
local index = self.gamepadFocusIndex;
if not index then
index = 0;
end
if delta < 0 and index < maxIndex then
index = index + 1;
elseif delta > 0 and index > 1 then
index = index - 1;
elseif index == 0 then
index = 1;
else
return
end
self:ClearGamePadFocus();
if self:FocusObjectByIndex(index) then
local threshold = 2 * OPTIONBUTTON_HEIGHT;
if delta > 0 then
local top = self.gamepadFocus:GetTop();
if top + threshold >= self.scrollFrameTop then
self.ScrollFrame:ScrollBy(-OPTIONBUTTON_HEIGHT);
end
else
local bottom = self.gamepadFocus:GetBottom();
if bottom - threshold <= self.scrollFrameBottom then
self.ScrollFrame:ScrollBy(OPTIONBUTTON_HEIGHT);
end
end
return true
end
end
function DUIDialogSettingsMixin:FocusNextObject()
if self:FocusObjectByDelta(1) then
return
end
end
function DUIDialogSettingsMixin:FocusPreviousObject()
if self:FocusObjectByDelta(-1) then
return
end
end
function DUIDialogSettingsMixin:ClickFocusedObject(gamepadButton)
if self.gamepadFocus then
local optionButton = self.gamepadFocus;
if gamepadButton == "PAD1" then
optionButton:OnClick();
elseif gamepadButton == "PADDLEFT" then
if optionButton.widgetType == "ArrowOption" then
optionButton.widget:SelectChoiceByDelta(-1);
end
elseif gamepadButton == "PADDRIGHT" then
if optionButton.widgetType == "ArrowOption" then
optionButton.widget:SelectChoiceByDelta(1);
end
end
return true
end
return false
end
end
function DialogueUI_ShowSettingsFrame()
MainFrame:ToggleUI();
end
function DialogueUI_AddonCompartmentOnEnterLeave(addonName, button)
end
do
local function OnFontSizeChanged(baseFontSize, fontSizeID)
FONT_HEIGHT_LARGE = baseFontSize;
FONT_HEIGHT_NORMAL = baseFontSize;
BUTTON_PADDING_LARGE = FONT_HEIGHT_NORMAL;
OPTIONBUTTON_HEIGHT = 3*FONT_HEIGHT_NORMAL;
OPTION_WIDGET_SIZE = 2 * FONT_HEIGHT_NORMAL;
local widthMultiplier;
if fontSizeID <= 1 then
NUM_VISIBLE_OPTIONS = 10.5;
widthMultiplier = 12;
ARROWOTPION_WIDTH_RATIO = 7;
ARROWOTPION_BAR_HEIGHT = 5;
elseif fontSizeID == 2 then
NUM_VISIBLE_OPTIONS = 9.5;
widthMultiplier = 11;
ARROWOTPION_WIDTH_RATIO = 7;
ARROWOTPION_BAR_HEIGHT = 6;
elseif fontSizeID == 3 then
NUM_VISIBLE_OPTIONS = 8.5;
widthMultiplier = 10;
ARROWOTPION_WIDTH_RATIO = 6;
ARROWOTPION_BAR_HEIGHT = 6;
else
NUM_VISIBLE_OPTIONS = 8.5;
widthMultiplier = 10;
ARROWOTPION_WIDTH_RATIO = 6;
ARROWOTPION_BAR_HEIGHT = 6;
end
OPTIONBUTTON_WIDTH = widthMultiplier * OPTIONBUTTON_HEIGHT;
end
addon.CallbackRegistry:Register("FontSizeChanged", OnFontSizeChanged);
local function PostFontSizeChanged()
--We wait after hotkey frame size update
local f = MainFrame;
if f.Init then return end;
if f.arrowOptionPool then
local function ModifyArrowOption(widget)
widget:SetWidgetHeight(OPTION_WIDGET_SIZE);
widget.numChoices = 0;
end
f.arrowOptionPool:ProcessAllObjects(ModifyArrowOption);
end
if f.hotkeyFramePool then
local method = "UpdateBaseHeight";
f.hotkeyFramePool:CallAllObjects(method);
end
f:Layout();
f:UpdateCurrentTab();
end
addon.CallbackRegistry:Register("PostFontSizeChanged", PostFontSizeChanged);
local function PostInputDeviceChanged(dbValue)
INPUT_DEVICE_GAME_PAD = dbValue ~= 1;
INPUT_DEVICE_ID = dbValue;
local f = MainFrame;
if f.Init then return end;
f:Layout();
f:UpdateCurrentTab();
end
addon.CallbackRegistry:Register("PostInputDeviceChanged", PostInputDeviceChanged);
end