Advertisement
Guest User

Untitled

a guest
Jan 25th, 2025
33
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.48 KB | None | 0 0
  1. -- Класс UniversalInfoFrame
  2. UniversalInfoFrame = {}
  3. UniversalInfoFrame.__index = UniversalInfoFrame
  4.  
  5. -- Конструктор
  6. function UniversalInfoFrame:new(updateInterval, saveTable)
  7.     -- Singleton проверка: возвращаем существующий экземпляр если он есть
  8.     if self.instance then
  9.         self.instance:Show() -- Показываем фрейм если был скрыт
  10.         return self.instance
  11.     end
  12.  
  13.     -- Инициализация нового объекта
  14.     local new_object = setmetatable({}, self)
  15.     self.__index = self
  16.  
  17.     -- Сохраняем экземпляр в классе
  18.     self.instance = new_object
  19.  
  20.     -- Инициализация параметров
  21.     new_object.saveTable = saveTable or {}
  22.     new_object.textsTop = {}
  23.     new_object.textsBottom = {}
  24.     new_object.updateInterval = updateInterval or 1
  25.     new_object.timeElapsed = 0
  26.     new_object.isCollapsed = false
  27.     new_object.collapsedText = nil
  28.  
  29.     -- Создание фрейма
  30.     new_object.frame = CreateFrame("Frame", nil, UIParent)
  31.     new_object.frame:SetSize(200, 50)
  32.     new_object.frame:SetPoint("CENTER")
  33.    
  34.     -- Конфигурация фрейма (без изменений)
  35.     new_object.frame:SetMovable(true)
  36.     new_object.frame:EnableMouse(true)
  37.     new_object.frame:RegisterForDrag("LeftButton")
  38.     new_object.frame:SetScript("OnDragStart", new_object.frame.StartMoving)
  39.     new_object.frame:SetScript("OnDragStop", new_object.frame.StopMovingOrSizing)
  40.    
  41.     new_object.frame:SetBackdrop({
  42.         bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
  43.         edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
  44.         tile = true, tileSize = 16, edgeSize = 16,
  45.         insets = { left = 4, right = 4, top = 4, bottom = 4 }
  46.     })
  47.     new_object.frame:SetBackdropColor(0, 0, 0, 0.8)
  48.  
  49.     -- Настройка скриптов
  50.     new_object.frame:SetScript("OnUpdate", function(_, elapsed)
  51.         new_object:OnUpdate(elapsed)
  52.     end)
  53.    
  54.     new_object.frame:SetScript("OnReceiveDrag", function()
  55.         new_object:OnReceiveDrag()
  56.     end)
  57.  
  58.     -- Восстановление сохраненных данных
  59.     for _, data in ipairs(new_object.saveTable) do
  60.         if data.description then
  61.             data.valueFunc = data.valueFunc or function() return "N/A" end
  62.             data.addToTop = data.addToTop == nil and true or data.addToTop
  63.             new_object:AddText(data.description, data.valueFunc, data.addToTop, true)
  64.         end
  65.     end
  66.  
  67.     return new_object
  68. end
  69.  
  70. function UniversalInfoFrame:UpdateSettings(newInterval, newSaveTable)
  71.     self.updateInterval = newInterval or self.updateInterval
  72.     if newSaveTable then
  73.         -- допишу
  74.     end
  75. end
  76.  
  77. -- Метод для обработки перетаскивания предмета на фрейм
  78. function UniversalInfoFrame:OnReceiveDrag()
  79.     local type, id, info = GetCursorInfo()
  80.     if type == "item" then
  81.         local name, _, quality = GetItemInfo(id)
  82.         if name then
  83.             self:AddText(name, function() return GetItemCount(id) end, true, false, id)
  84.         end
  85.         ClearCursor()
  86.     end
  87. end
  88.  
  89. -- Метод для добавления текстового поля
  90. function UniversalInfoFrame:AddText(description, valueFunc, addToTop, isRestore, itemID)
  91.     valueFunc = valueFunc or function() return "N/A" end  -- Устанавливаем значение по умолчанию
  92.  
  93.     -- Добавляем двоеточие после названия строки
  94.     local headerTextStr = description .. ":"
  95.  
  96.     -- Получаем цвет качества, если передан itemID
  97.     local r, g, b = 1, 1, 1  -- Белый цвет по умолчанию
  98.     if itemID then
  99.         local _, _, quality = GetItemInfo(itemID)
  100.         if quality then
  101.             r, g, b = GetItemQualityColor(quality)
  102.         end
  103.     end
  104.  
  105.     -- Создаем текстовое поле для заголовка
  106.     local headerText = self.frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  107.     headerText:SetJustifyH("LEFT")
  108.     headerText:SetText(headerTextStr)
  109.     headerText:SetTextColor(r, g, b)
  110.  
  111.     -- Создаем текстовое поле для данных
  112.     local valueText = self.frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
  113.     valueText:SetJustifyH("LEFT")
  114.     valueText:SetText(tostring(valueFunc()))
  115.     valueText:SetTextColor(0.59, 0.98, 0.59)  -- Светло-зелёный цвет для данных
  116.  
  117.     -- Создаем фрейм для кликабельной области
  118.     local clickFrame = CreateFrame("Frame", nil, self.frame)
  119.     clickFrame:SetAllPoints(headerText)
  120.     clickFrame:EnableMouse(true)
  121.     clickFrame:SetScript("OnMouseDown", function(_, button)
  122.         if button == "LeftButton" then
  123.             self:ToggleCollapse(headerText, valueText)
  124.         elseif button == "RightButton" and not self.isCollapsed then
  125.             self:RemoveText(headerText, valueText)
  126.         end
  127.     end)
  128.  
  129.     -- Добавляем текстовые поля в верхнюю или нижнюю часть фрейма
  130.     local targetTable = addToTop and self.textsTop or self.textsBottom
  131.     table.insert(targetTable, { description = description, valueFunc = valueFunc, headerText = headerText, valueText = valueText, clickFrame = clickFrame })
  132.  
  133.     -- Сохраняем строку в таблицу сохранения, если это не восстановление
  134.     if not isRestore then
  135.         table.insert(self.saveTable, { description = description, valueFunc = valueFunc, addToTop = addToTop })
  136.     end
  137.  
  138.     -- Обновляем позиции всех текстовых полей и размер фрейма
  139.     self:UpdateTextPositions()
  140.     self:UpdateFrameSize()
  141. end
  142.  
  143. -- Метод для удаления текстового поля
  144. function UniversalInfoFrame:RemoveText(headerText, valueText)
  145.     if not headerText or not valueText then return end
  146.  
  147.     local headerTextStr = headerText:GetText()
  148.     if not headerTextStr then return end
  149.  
  150.     -- Локальная функция для удаления из указанной таблицы
  151.     local function removeFromTable(tbl)
  152.         for i = #tbl, 1, -1 do -- Итерируем с конца для безопасного удаления
  153.             local data = tbl[i]
  154.             if data.headerText and data.headerText:GetText() == headerTextStr then
  155.                 -- Удаляем кликабельную область
  156.                 if data.clickFrame then
  157.                     data.clickFrame:Hide()
  158.                     data.clickFrame:SetScript("OnMouseDown", nil)
  159.                 end
  160.  
  161.                 -- Удаляем текстовые поля
  162.                 if data.headerText then
  163.                     data.headerText:Hide()
  164.                     data.headerText:SetText("")
  165.                 end
  166.  
  167.                 if data.valueText then
  168.                     data.valueText:Hide()
  169.                     data.valueText:SetText("")
  170.                 end
  171.  
  172.                 -- Удаляем из saveTable
  173.                 for j = #self.saveTable, 1, -1 do
  174.                     if self.saveTable[j].description == data.description then
  175.                         table.remove(self.saveTable, j)
  176.                         break
  177.                     end
  178.                 end
  179.  
  180.                 -- Удаляем запись из основной таблицы
  181.                 table.remove(tbl, i)
  182.                 break
  183.             end
  184.         end
  185.     end
  186.  
  187.     -- Удаляем из обеих таблиц
  188.     removeFromTable(self.textsTop)
  189.     removeFromTable(self.textsBottom)
  190.  
  191.     -- Если фрейм был свёрнут, разворачиваем
  192.     if self.isCollapsed then
  193.         self.isCollapsed = false
  194.         self.collapsedText = nil
  195.         -- Показываем все текстовые поля
  196.         self:UpdateTextVisibility(true)
  197.     end
  198.  
  199.     -- Обновляем интерфейс
  200.     self:UpdateTextPositions()
  201.     self:UpdateFrameSize()
  202. end
  203.  
  204. -- Метод для обновления позиций текстовых полей
  205. function UniversalInfoFrame:UpdateTextPositions()
  206.     -- Очищаем все точки привязки
  207.     for _, data in ipairs(self.textsTop) do
  208.         data.headerText:ClearAllPoints()
  209.         data.valueText:ClearAllPoints()
  210.     end
  211.     for _, data in ipairs(self.textsBottom) do
  212.         data.headerText:ClearAllPoints()
  213.         data.valueText:ClearAllPoints()
  214.     end
  215.  
  216.     -- Находим максимальную ширину заголовка
  217.     local maxHeaderWidth = 0
  218.     for _, data in ipairs(self.textsTop) do
  219.         local width = data.headerText:GetStringWidth()
  220.         if width > maxHeaderWidth then
  221.             maxHeaderWidth = width
  222.         end
  223.     end
  224.     for _, data in ipairs(self.textsBottom) do
  225.         local width = data.headerText:GetStringWidth()
  226.         if width > maxHeaderWidth then
  227.             maxHeaderWidth = width
  228.         end
  229.     end
  230.  
  231.     -- Позиционируем текстовые поля в верхней части
  232.     for i, data in ipairs(self.textsTop) do
  233.         if i == 1 then
  234.             data.headerText:SetPoint("TOPLEFT", 10, -10)  -- Первое поле в верхней части
  235.         else
  236.             data.headerText:SetPoint("TOPLEFT", self.textsTop[i - 1].headerText, "BOTTOMLEFT", 0, -5)  -- Остальные поля
  237.         end
  238.         -- Позиционируем значение на той же строке, что и заголовок
  239.         data.valueText:SetPoint("LEFT", data.headerText, "RIGHT", 5, 0)
  240.     end
  241.  
  242.     -- Позиционируем текстовые поля в нижней части
  243.     for i, data in ipairs(self.textsBottom) do
  244.         if i == 1 then
  245.             data.headerText:SetPoint("BOTTOMLEFT", 10, 10)  -- Первое поле в нижней части
  246.         else
  247.             data.headerText:SetPoint("BOTTOMLEFT", self.textsBottom[i - 1].headerText, "TOPLEFT", 0, 5)  -- Остальные поля
  248.         end
  249.         -- Позиционируем значение на той же строке, что и заголовок
  250.         data.valueText:SetPoint("LEFT", data.headerText, "RIGHT", 5, 0)
  251.     end
  252. end
  253.  
  254. -- Метод для обновления текстовых полей
  255. function UniversalInfoFrame:UpdateTexts()
  256.     for _, data in ipairs(self.textsTop) do
  257.         local value = data.valueFunc()
  258.         data.valueText:SetText(tostring(value))
  259.     end
  260.  
  261.     for _, data in ipairs(self.textsBottom) do
  262.         local value = data.valueFunc()
  263.         data.valueText:SetText(tostring(value))
  264.     end
  265.  
  266.     -- Обновляем размер фрейма после изменения текста
  267.     self:UpdateFrameSize()
  268. end
  269.  
  270. -- Метод для обновления размера фрейма
  271. function UniversalInfoFrame:UpdateFrameSize()
  272.     if self.isCollapsed and self.collapsedText then
  273.         -- В свёрнутом состоянии фрейм имеет фиксированную высоту
  274.         local headerText = self.collapsedText.headerText
  275.         local valueText = self.collapsedText.valueText
  276.  
  277.         if headerText and valueText then
  278.             local headerWidth = headerText:GetStringWidth()
  279.             local valueWidth = valueText:GetStringWidth()
  280.             local totalWidth = headerWidth + valueWidth + 15  -- Учитываем отступ между заголовком и значением
  281.  
  282.             -- Устанавливаем размер фрейма
  283.             self.frame:SetHeight(30)  -- Высота одной строки
  284.             self.frame:SetWidth(totalWidth + 20)  -- Ширина текста с отступами
  285.  
  286.             -- Позиционируем заголовок и значение в центре фрейма
  287.             headerText:ClearAllPoints()
  288.             headerText:SetPoint("LEFT", self.frame, "LEFT", 10, 0)
  289.             valueText:ClearAllPoints()
  290.             valueText:SetPoint("LEFT", headerText, "RIGHT", 5, 0)
  291.         end
  292.     else
  293.         -- В развёрнутом состоянии фрейм подстраивается под содержимое
  294.         local totalHeight = 0
  295.         local maxTotalWidth = 0
  296.  
  297.         -- Вычисляем общую высоту и максимальную ширину текстовых полей
  298.         for _, data in ipairs(self.textsTop) do
  299.             local headerText = data.headerText
  300.             local valueText = data.valueText
  301.             totalHeight = totalHeight + 20  -- Высота одного текстового поля
  302.  
  303.             local headerWidth = headerText:GetStringWidth()
  304.             local valueWidth = valueText:GetStringWidth()
  305.             local totalWidth = headerWidth + valueWidth + 15  -- Учитываем отступ между заголовком и данными
  306.             if totalWidth > maxTotalWidth then
  307.                 maxTotalWidth = totalWidth
  308.             end
  309.         end
  310.  
  311.         for _, data in ipairs(self.textsBottom) do
  312.             local headerText = data.headerText
  313.             local valueText = data.valueText
  314.             totalHeight = totalHeight + 20  -- Высота одного текстового поля
  315.  
  316.             local headerWidth = headerText:GetStringWidth()
  317.             local valueWidth = valueText:GetStringWidth()
  318.             local totalWidth = headerWidth + valueWidth + 15  -- Учитываем отступ между заголовком и данными
  319.             if totalWidth > maxTotalWidth then
  320.                 maxTotalWidth = totalWidth
  321.             end
  322.         end
  323.  
  324.         -- Устанавливаем новый размер фрейма
  325.         self.frame:SetHeight(totalHeight + 20)  -- Добавляем отступы
  326.         self.frame:SetWidth(maxTotalWidth + 20)  -- Ширина самой длинной строки + отступы
  327.     end
  328. end
  329.  
  330. -- Метод для сворачивания/разворачивания фрейма
  331. function UniversalInfoFrame:ToggleCollapse(headerText, valueText)
  332.     if self.isCollapsed then
  333.         -- Разворачиваем фрейм
  334.         self.isCollapsed = false
  335.         self.collapsedText = nil
  336.  
  337.         -- Показываем все текстовые поля
  338.         for _, data in ipairs(self.textsTop) do
  339.             data.headerText:Show()
  340.             data.valueText:Show()
  341.         end
  342.         for _, data in ipairs(self.textsBottom) do
  343.             data.headerText:Show()
  344.             data.valueText:Show()
  345.         end
  346.     else
  347.         -- Сворачиваем фрейм
  348.         self.isCollapsed = true
  349.  
  350.         -- Находим данные для свёрнутого текста
  351.         for _, data in ipairs(self.textsTop) do
  352.             if data.headerText == headerText then
  353.                 self.collapsedText = data
  354.                 break
  355.             end
  356.         end
  357.         for _, data in ipairs(self.textsBottom) do
  358.             if data.headerText == headerText then
  359.                 self.collapsedText = data
  360.                 break
  361.             end
  362.         end
  363.  
  364.         -- Скрываем все текстовые поля, кроме выбранного
  365.         for _, data in ipairs(self.textsTop) do
  366.             if data.headerText ~= headerText then
  367.                 data.headerText:Hide()
  368.                 data.valueText:Hide()
  369.             end
  370.         end
  371.         for _, data in ipairs(self.textsBottom) do
  372.             if data.headerText ~= headerText then
  373.                 data.headerText:Hide()
  374.                 data.valueText:Hide()
  375.             end
  376.         end
  377.     end
  378.  
  379.     -- Обновляем позиции всех текстовых полей и размер фрейма
  380.     self:UpdateTextPositions()
  381.     self:UpdateFrameSize()
  382. end
  383.  
  384. -- Метод для обработки обновления фрейма
  385. function UniversalInfoFrame:OnUpdate(elapsed)
  386.     self.timeElapsed = self.timeElapsed + elapsed
  387.     if self.timeElapsed > self.updateInterval then
  388.         self.timeElapsed = 0
  389.         self:UpdateTexts()  -- Обновляем текстовые поля
  390.     end
  391. end
  392.  
  393. -- Метод для отображения фрейма
  394. function UniversalInfoFrame:Show()
  395.     self.frame:Show()
  396. end
  397.  
  398. -- Метод для скрытия фрейма
  399. function UniversalInfoFrame:Hide()
  400.     self.frame:Hide()
  401. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement