Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Класс UniversalInfoFrame
- UniversalInfoFrame = {}
- UniversalInfoFrame.__index = UniversalInfoFrame
- -- Конструктор
- function UniversalInfoFrame:new(updateInterval, saveTable)
- -- Singleton проверка: возвращаем существующий экземпляр если он есть
- if self.instance then
- self.instance:Show() -- Показываем фрейм если был скрыт
- return self.instance
- end
- -- Инициализация нового объекта
- local new_object = setmetatable({}, self)
- self.__index = self
- -- Сохраняем экземпляр в классе
- self.instance = new_object
- -- Инициализация параметров
- new_object.saveTable = saveTable or {}
- new_object.textsTop = {}
- new_object.textsBottom = {}
- new_object.updateInterval = updateInterval or 1
- new_object.timeElapsed = 0
- new_object.isCollapsed = false
- new_object.collapsedText = nil
- -- Создание фрейма
- new_object.frame = CreateFrame("Frame", nil, UIParent)
- new_object.frame:SetSize(200, 50)
- new_object.frame:SetPoint("CENTER")
- -- Конфигурация фрейма (без изменений)
- new_object.frame:SetMovable(true)
- new_object.frame:EnableMouse(true)
- new_object.frame:RegisterForDrag("LeftButton")
- new_object.frame:SetScript("OnDragStart", new_object.frame.StartMoving)
- new_object.frame:SetScript("OnDragStop", new_object.frame.StopMovingOrSizing)
- new_object.frame:SetBackdrop({
- bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
- edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
- tile = true, tileSize = 16, edgeSize = 16,
- insets = { left = 4, right = 4, top = 4, bottom = 4 }
- })
- new_object.frame:SetBackdropColor(0, 0, 0, 0.8)
- -- Настройка скриптов
- new_object.frame:SetScript("OnUpdate", function(_, elapsed)
- new_object:OnUpdate(elapsed)
- end)
- new_object.frame:SetScript("OnReceiveDrag", function()
- new_object:OnReceiveDrag()
- end)
- -- Восстановление сохраненных данных
- for _, data in ipairs(new_object.saveTable) do
- if data.description then
- data.valueFunc = data.valueFunc or function() return "N/A" end
- data.addToTop = data.addToTop == nil and true or data.addToTop
- new_object:AddText(data.description, data.valueFunc, data.addToTop, true)
- end
- end
- return new_object
- end
- function UniversalInfoFrame:UpdateSettings(newInterval, newSaveTable)
- self.updateInterval = newInterval or self.updateInterval
- if newSaveTable then
- -- допишу
- end
- end
- -- Метод для обработки перетаскивания предмета на фрейм
- function UniversalInfoFrame:OnReceiveDrag()
- local type, id, info = GetCursorInfo()
- if type == "item" then
- local name, _, quality = GetItemInfo(id)
- if name then
- self:AddText(name, function() return GetItemCount(id) end, true, false, id)
- end
- ClearCursor()
- end
- end
- -- Метод для добавления текстового поля
- function UniversalInfoFrame:AddText(description, valueFunc, addToTop, isRestore, itemID)
- valueFunc = valueFunc or function() return "N/A" end -- Устанавливаем значение по умолчанию
- -- Добавляем двоеточие после названия строки
- local headerTextStr = description .. ":"
- -- Получаем цвет качества, если передан itemID
- local r, g, b = 1, 1, 1 -- Белый цвет по умолчанию
- if itemID then
- local _, _, quality = GetItemInfo(itemID)
- if quality then
- r, g, b = GetItemQualityColor(quality)
- end
- end
- -- Создаем текстовое поле для заголовка
- local headerText = self.frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
- headerText:SetJustifyH("LEFT")
- headerText:SetText(headerTextStr)
- headerText:SetTextColor(r, g, b)
- -- Создаем текстовое поле для данных
- local valueText = self.frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
- valueText:SetJustifyH("LEFT")
- valueText:SetText(tostring(valueFunc()))
- valueText:SetTextColor(0.59, 0.98, 0.59) -- Светло-зелёный цвет для данных
- -- Создаем фрейм для кликабельной области
- local clickFrame = CreateFrame("Frame", nil, self.frame)
- clickFrame:SetAllPoints(headerText)
- clickFrame:EnableMouse(true)
- clickFrame:SetScript("OnMouseDown", function(_, button)
- if button == "LeftButton" then
- self:ToggleCollapse(headerText, valueText)
- elseif button == "RightButton" and not self.isCollapsed then
- self:RemoveText(headerText, valueText)
- end
- end)
- -- Добавляем текстовые поля в верхнюю или нижнюю часть фрейма
- local targetTable = addToTop and self.textsTop or self.textsBottom
- table.insert(targetTable, { description = description, valueFunc = valueFunc, headerText = headerText, valueText = valueText, clickFrame = clickFrame })
- -- Сохраняем строку в таблицу сохранения, если это не восстановление
- if not isRestore then
- table.insert(self.saveTable, { description = description, valueFunc = valueFunc, addToTop = addToTop })
- end
- -- Обновляем позиции всех текстовых полей и размер фрейма
- self:UpdateTextPositions()
- self:UpdateFrameSize()
- end
- -- Метод для удаления текстового поля
- function UniversalInfoFrame:RemoveText(headerText, valueText)
- if not headerText or not valueText then return end
- local headerTextStr = headerText:GetText()
- if not headerTextStr then return end
- -- Локальная функция для удаления из указанной таблицы
- local function removeFromTable(tbl)
- for i = #tbl, 1, -1 do -- Итерируем с конца для безопасного удаления
- local data = tbl[i]
- if data.headerText and data.headerText:GetText() == headerTextStr then
- -- Удаляем кликабельную область
- if data.clickFrame then
- data.clickFrame:Hide()
- data.clickFrame:SetScript("OnMouseDown", nil)
- end
- -- Удаляем текстовые поля
- if data.headerText then
- data.headerText:Hide()
- data.headerText:SetText("")
- end
- if data.valueText then
- data.valueText:Hide()
- data.valueText:SetText("")
- end
- -- Удаляем из saveTable
- for j = #self.saveTable, 1, -1 do
- if self.saveTable[j].description == data.description then
- table.remove(self.saveTable, j)
- break
- end
- end
- -- Удаляем запись из основной таблицы
- table.remove(tbl, i)
- break
- end
- end
- end
- -- Удаляем из обеих таблиц
- removeFromTable(self.textsTop)
- removeFromTable(self.textsBottom)
- -- Если фрейм был свёрнут, разворачиваем
- if self.isCollapsed then
- self.isCollapsed = false
- self.collapsedText = nil
- -- Показываем все текстовые поля
- self:UpdateTextVisibility(true)
- end
- -- Обновляем интерфейс
- self:UpdateTextPositions()
- self:UpdateFrameSize()
- end
- -- Метод для обновления позиций текстовых полей
- function UniversalInfoFrame:UpdateTextPositions()
- -- Очищаем все точки привязки
- for _, data in ipairs(self.textsTop) do
- data.headerText:ClearAllPoints()
- data.valueText:ClearAllPoints()
- end
- for _, data in ipairs(self.textsBottom) do
- data.headerText:ClearAllPoints()
- data.valueText:ClearAllPoints()
- end
- -- Находим максимальную ширину заголовка
- local maxHeaderWidth = 0
- for _, data in ipairs(self.textsTop) do
- local width = data.headerText:GetStringWidth()
- if width > maxHeaderWidth then
- maxHeaderWidth = width
- end
- end
- for _, data in ipairs(self.textsBottom) do
- local width = data.headerText:GetStringWidth()
- if width > maxHeaderWidth then
- maxHeaderWidth = width
- end
- end
- -- Позиционируем текстовые поля в верхней части
- for i, data in ipairs(self.textsTop) do
- if i == 1 then
- data.headerText:SetPoint("TOPLEFT", 10, -10) -- Первое поле в верхней части
- else
- data.headerText:SetPoint("TOPLEFT", self.textsTop[i - 1].headerText, "BOTTOMLEFT", 0, -5) -- Остальные поля
- end
- -- Позиционируем значение на той же строке, что и заголовок
- data.valueText:SetPoint("LEFT", data.headerText, "RIGHT", 5, 0)
- end
- -- Позиционируем текстовые поля в нижней части
- for i, data in ipairs(self.textsBottom) do
- if i == 1 then
- data.headerText:SetPoint("BOTTOMLEFT", 10, 10) -- Первое поле в нижней части
- else
- data.headerText:SetPoint("BOTTOMLEFT", self.textsBottom[i - 1].headerText, "TOPLEFT", 0, 5) -- Остальные поля
- end
- -- Позиционируем значение на той же строке, что и заголовок
- data.valueText:SetPoint("LEFT", data.headerText, "RIGHT", 5, 0)
- end
- end
- -- Метод для обновления текстовых полей
- function UniversalInfoFrame:UpdateTexts()
- for _, data in ipairs(self.textsTop) do
- local value = data.valueFunc()
- data.valueText:SetText(tostring(value))
- end
- for _, data in ipairs(self.textsBottom) do
- local value = data.valueFunc()
- data.valueText:SetText(tostring(value))
- end
- -- Обновляем размер фрейма после изменения текста
- self:UpdateFrameSize()
- end
- -- Метод для обновления размера фрейма
- function UniversalInfoFrame:UpdateFrameSize()
- if self.isCollapsed and self.collapsedText then
- -- В свёрнутом состоянии фрейм имеет фиксированную высоту
- local headerText = self.collapsedText.headerText
- local valueText = self.collapsedText.valueText
- if headerText and valueText then
- local headerWidth = headerText:GetStringWidth()
- local valueWidth = valueText:GetStringWidth()
- local totalWidth = headerWidth + valueWidth + 15 -- Учитываем отступ между заголовком и значением
- -- Устанавливаем размер фрейма
- self.frame:SetHeight(30) -- Высота одной строки
- self.frame:SetWidth(totalWidth + 20) -- Ширина текста с отступами
- -- Позиционируем заголовок и значение в центре фрейма
- headerText:ClearAllPoints()
- headerText:SetPoint("LEFT", self.frame, "LEFT", 10, 0)
- valueText:ClearAllPoints()
- valueText:SetPoint("LEFT", headerText, "RIGHT", 5, 0)
- end
- else
- -- В развёрнутом состоянии фрейм подстраивается под содержимое
- local totalHeight = 0
- local maxTotalWidth = 0
- -- Вычисляем общую высоту и максимальную ширину текстовых полей
- for _, data in ipairs(self.textsTop) do
- local headerText = data.headerText
- local valueText = data.valueText
- totalHeight = totalHeight + 20 -- Высота одного текстового поля
- local headerWidth = headerText:GetStringWidth()
- local valueWidth = valueText:GetStringWidth()
- local totalWidth = headerWidth + valueWidth + 15 -- Учитываем отступ между заголовком и данными
- if totalWidth > maxTotalWidth then
- maxTotalWidth = totalWidth
- end
- end
- for _, data in ipairs(self.textsBottom) do
- local headerText = data.headerText
- local valueText = data.valueText
- totalHeight = totalHeight + 20 -- Высота одного текстового поля
- local headerWidth = headerText:GetStringWidth()
- local valueWidth = valueText:GetStringWidth()
- local totalWidth = headerWidth + valueWidth + 15 -- Учитываем отступ между заголовком и данными
- if totalWidth > maxTotalWidth then
- maxTotalWidth = totalWidth
- end
- end
- -- Устанавливаем новый размер фрейма
- self.frame:SetHeight(totalHeight + 20) -- Добавляем отступы
- self.frame:SetWidth(maxTotalWidth + 20) -- Ширина самой длинной строки + отступы
- end
- end
- -- Метод для сворачивания/разворачивания фрейма
- function UniversalInfoFrame:ToggleCollapse(headerText, valueText)
- if self.isCollapsed then
- -- Разворачиваем фрейм
- self.isCollapsed = false
- self.collapsedText = nil
- -- Показываем все текстовые поля
- for _, data in ipairs(self.textsTop) do
- data.headerText:Show()
- data.valueText:Show()
- end
- for _, data in ipairs(self.textsBottom) do
- data.headerText:Show()
- data.valueText:Show()
- end
- else
- -- Сворачиваем фрейм
- self.isCollapsed = true
- -- Находим данные для свёрнутого текста
- for _, data in ipairs(self.textsTop) do
- if data.headerText == headerText then
- self.collapsedText = data
- break
- end
- end
- for _, data in ipairs(self.textsBottom) do
- if data.headerText == headerText then
- self.collapsedText = data
- break
- end
- end
- -- Скрываем все текстовые поля, кроме выбранного
- for _, data in ipairs(self.textsTop) do
- if data.headerText ~= headerText then
- data.headerText:Hide()
- data.valueText:Hide()
- end
- end
- for _, data in ipairs(self.textsBottom) do
- if data.headerText ~= headerText then
- data.headerText:Hide()
- data.valueText:Hide()
- end
- end
- end
- -- Обновляем позиции всех текстовых полей и размер фрейма
- self:UpdateTextPositions()
- self:UpdateFrameSize()
- end
- -- Метод для обработки обновления фрейма
- function UniversalInfoFrame:OnUpdate(elapsed)
- self.timeElapsed = self.timeElapsed + elapsed
- if self.timeElapsed > self.updateInterval then
- self.timeElapsed = 0
- self:UpdateTexts() -- Обновляем текстовые поля
- end
- end
- -- Метод для отображения фрейма
- function UniversalInfoFrame:Show()
- self.frame:Show()
- end
- -- Метод для скрытия фрейма
- function UniversalInfoFrame:Hide()
- self.frame:Hide()
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement