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.

324 lines
9.4 KiB

local _, addon = ...
local API = addon.API;
local TooltipFrame = addon.SharedTooltip;
local Clamp = API.Clamp;
local GetCursorPosition = GetCursorPosition;
--widgets are created on-use
local FRAME_WIDTH = 480;
local FRAME_HEIGHT = 480
local FRAME_INSET = 12;
local EDITBOX_TEXT_INSET = 4;
local SCROLLBAR_WIDTH = 12;
local Clipboard = CreateFrame("Frame");
addon.Clipboard = Clipboard;
Clipboard:Hide();
Clipboard:EnableMouse(true);
Clipboard:SetToplevel(true);
local CopyTextButtons = {};
local EditBoxMixin = {};
do
function EditBoxMixin:OnTextChanged(userInput)
if userInput then
Clipboard:Hide();
return
end
C_Timer.After(0, function()
self:GetParent():UpdateScrollChildRect(); --?
self:GetParent():UpdateScrollRange();
end);
end
function EditBoxMixin:OnEscapePressed()
Clipboard:Hide();
end
function EditBoxMixin:OnEditFocusGained()
end
function EditBoxMixin:OnEditFocusLost()
end
end
local ScrollFrameMixin = {};
do
local OFFSET_PER_SCROLL = 24; --two lines
function ScrollFrameMixin:SetScrollOffset(scrollOffset)
scrollOffset = Clamp(scrollOffset, 0, self.range);
self.scrollOffset = scrollOffset;
self:SetVerticalScroll(scrollOffset);
self.scrollBar:UpdateThumbPosition();
end
function ScrollFrameMixin:ScrollBy(offset)
self:SetScrollOffset(self:GetVerticalScroll() + offset)
end
function ScrollFrameMixin:OnMouseWheel(delta)
if delta > 0 then
self:ScrollBy(-OFFSET_PER_SCROLL);
else
self:ScrollBy(OFFSET_PER_SCROLL);
end
end
function ScrollFrameMixin:ScrollToTop()
self:SetScrollOffset(0);
end
function ScrollFrameMixin:ScrollToBottom()
self:SetScrollOffset(self:GetVerticalScrollRange());
end
function ScrollFrameMixin:UpdateScrollRange()
local range = self:GetVerticalScrollRange();
if range <= 0 then
range = 0;
self.scrollBar:Hide();
else
self.scrollBar:Show();
end
local diff = self.range and (self.range - range) or 0;
local resetScrollOffset = diff < -1 or diff > 1;
self.range = range;
self.scrollBar:UpdateThumbSize();
if resetScrollOffset then
self:ScrollToTop();
end
end
function ScrollFrameMixin:SetScrollBar(scrollBar)
self.scrollBar = scrollBar;
scrollBar:SetOwner(self);
end
function ScrollFrameMixin:GetScrollOffset()
return self.scrollOffset or self:GetVerticalScroll();
end
function ScrollFrameMixin:GetScrollRange()
return self.range or self:GetVerticalScrollRange()
end
function ScrollFrameMixin:GetViewSize()
return self:GetHeight()
end
end
function Clipboard:StartCursorScrolling()
self.cursorTop = self:GetTop() - FRAME_INSET;
self.cursorBottom = self:GetBottom() + FRAME_INSET;
self.t = 0;
self.interval = 0.25;
self:SetScript("OnUpdate", self.OnUpdate);
end
function Clipboard:StopCursorScrolling()
self:SetScript("OnUpdate", nil);
self.t = nil;
end
function Clipboard:OnUpdate(elapsed)
self.t = self.t + elapsed;
if self.t >= self.interval then
local delta;
local _, cursorY = GetCursorPosition();
if cursorY > self.cursorTop then
if self.t > 0.25 then
self.t = elapsed;
end
delta = (self.cursorTop - cursorY) * self.t * 10;
self.interval = 0.016;
elseif cursorY < self.cursorBottom then
if self.t > 0.25 then
self.t = elapsed;
end
delta = (self.cursorBottom - cursorY) * self.t * 10;
self.interval = 0.016;
else
self.interval = 0.5;
end
self.t = 0;
if delta then
self.ScrollFrame:ScrollBy(delta);
end
end
end
function Clipboard:Init()
self:SetSize(FRAME_WIDTH, FRAME_HEIGHT);
self:SetPoint("CENTER", UIParent, "CENTER", 0, 0);
self:SetFrameStrata("DIALOG");
local bg = self:CreateTexture(nil, "BACKGROUND");
bg:SetAllPoints(true);
local corner = 16;
bg:SetTextureSliceMargins(corner, corner, corner, corner);
bg:SetTextureSliceMode(1);
bg:SetTexture("Interface/AddOns/DialogueUI/Art/Theme_Shared/ClipboardBackground.png");
API.UpdateTextureSliceScale(bg);
local ScrollBar = addon.CreateScrollBar(self);
self.ScrollBar = ScrollBar;
ScrollBar:SetPoint("TOPRIGHT", self, "TOPRIGHT", -FRAME_INSET, -FRAME_INSET);
ScrollBar:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -FRAME_INSET, FRAME_INSET);
ScrollBar:SetAlwaysVisible(true);
ScrollBar:SetTheme(2);
ScrollBar:Show();
local ScrollFrame = CreateFrame("ScrollFrame", nil, self);
self.ScrollFrame = ScrollFrame;
ScrollFrame:SetPoint("TOPLEFT", self, "TOPLEFT", FRAME_INSET, -FRAME_INSET);
ScrollFrame:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -(FRAME_INSET + SCROLLBAR_WIDTH + FRAME_INSET), FRAME_INSET);
local EditBox = CreateFrame("EditBox", nil, ScrollFrame);
self.EditBox = EditBox;
local eidtBoxWidth = FRAME_WIDTH - 3*FRAME_INSET - SCROLLBAR_WIDTH;
EditBox:SetFontObject("DUIFont_Quest_Quest");
--EditBox:SetTextColor(1, 1, 1);
EditBox:SetAutoFocus(false);
EditBox:SetMultiLine(true);
--EditBox:SetVisibleTextByteLimit(32); --Not just being invisible, but truncated
EditBox:SetHighlightColor(0, 0.471, 0.843);
EditBox:SetPoint("TOPLEFT");
EditBox:SetWidth(eidtBoxWidth)
EditBox:SetHeight(1);
EditBox:SetTextInsets(EDITBOX_TEXT_INSET, EDITBOX_TEXT_INSET, EDITBOX_TEXT_INSET, EDITBOX_TEXT_INSET);
ScrollFrame:SetScrollChild(EditBox);
API.Mixin(EditBox, EditBoxMixin);
EditBox:SetScript("OnTextChanged", EditBox.OnTextChanged);
EditBox:SetScript("OnEscapePressed", EditBox.OnEscapePressed);
API.Mixin(ScrollFrame, ScrollFrameMixin);
ScrollFrame:SetScript("OnMouseWheel", ScrollFrame.OnMouseWheel);
ScrollFrame:SetScrollBar(ScrollBar);
self.Init = nil;
end
function Clipboard:ShowContent(text, senderCopyButton)
if self.Init then
self:Init();
end
self.EditBox:SetText(text);
self:Show();
self.sender = senderCopyButton;
end
function Clipboard:IsFromSameSender(sender)
return self.sender and self.sender == sender
end
function Clipboard:CloseIfFromSameSender(sender)
if self:IsFromSameSender(sender) then
self:Hide();
return true
end
end
function Clipboard:OnShow()
self:RegisterEvent("GLOBAL_MOUSE_DOWN");
self:RegisterEvent("GLOBAL_MOUSE_UP");
end
Clipboard:SetScript("OnShow", Clipboard.OnShow);
function Clipboard:OnEvent(event, ...)
if event == "GLOBAL_MOUSE_DOWN" then
if self:IsMouseOver() then
if self.EditBox:IsMouseOver() then
self:StartCursorScrolling();
end
else
for i, button in ipairs(CopyTextButtons) do
if button:IsMouseOver() then
return
end
end
self:Hide();
end
elseif event == "GLOBAL_MOUSE_UP" then
self:StopCursorScrolling();
end
end
Clipboard:SetScript("OnEvent", Clipboard.OnEvent);
function Clipboard:OnHide()
self.sender = nil;
self:UnregisterEvent("GLOBAL_MOUSE_DOWN");
self:UnregisterEvent("GLOBAL_MOUSE_UP");
self.EditBox:SetText("");
self.EditBox:ClearHighlightText();
self:StopCursorScrolling();
end
Clipboard:SetScript("OnHide", Clipboard.OnHide);
do --Copy Text Button
local BUTTON_SIZE = 24;
local ICON_SIZE = 16;
local ALPHA_UNFOCUSED = 0.6;
local CopyTextButtonMixin = {};
function CopyTextButtonMixin:OnEnter()
self.Icon:SetAlpha(1);
TooltipFrame:Hide();
TooltipFrame:SetOwner(self, "TOPRIGHT");
TooltipFrame:AddLeftLine(addon.L["Copy Text"], 1, 1, 1);
TooltipFrame:Show();
end
function CopyTextButtonMixin:OnLeave()
self.Icon:SetAlpha(ALPHA_UNFOCUSED);
TooltipFrame:Hide();
end
function CopyTextButtonMixin:SetTheme(themeID)
if themeID == 1 then
self.Icon:SetTexCoord(0, 0.5, 0, 1); --Brown, white stroke
else
self.Icon:SetTexCoord(0.5, 1, 0, 1); --Grey, black stroke
end
end
local function CreateCopyTextButton(parent, onClickFunc, themeID)
local b = CreateFrame("Button", nil, parent);
b:SetSize(BUTTON_SIZE, BUTTON_SIZE);
b.Icon = b:CreateTexture(nil, "OVERLAY");
b.Icon:SetSize(ICON_SIZE, ICON_SIZE);
b.Icon:SetPoint("CENTER", b, "CENTER", 0, 0);
b.Icon:SetTexture("Interface/AddOns/DialogueUI/Art/Theme_Shared/CopyTextButton.png");
b.Icon:SetAlpha(ALPHA_UNFOCUSED);
API.Mixin(b, CopyTextButtonMixin);
b:SetScript("OnClick", onClickFunc);
b:SetScript("OnEnter", b.OnEnter);
b:SetScript("OnLeave", b.OnLeave);
b:SetTheme(themeID);
table.insert(CopyTextButtons, b);
return b
end
addon.CreateCopyTextButton = CreateCopyTextButton;
end