first commit

This commit is contained in:
Salikh Gurgenidze
2025-11-16 04:47:49 +04:00
commit aec33e3652
22 changed files with 3752 additions and 0 deletions
+658
View File
@@ -0,0 +1,658 @@
-- Guda Bag Frame
-- Main bag viewing UI
local addon = Guda
local BagFrame = {}
addon.Modules.BagFrame = BagFrame
local currentViewChar = nil -- nil = current character
local searchText = ""
local itemButtons = {}
-- Global click catcher for clearing search focus
local clickCatcher = nil
-- OnLoad
function Guda_BagFrame_OnLoad(self)
-- Set up search box placeholder
local searchBox = getglobal(self:GetName().."_SearchBar_SearchBox")
if searchBox then
searchBox:SetText("Search, try ~equipment")
searchBox:SetTextColor(0.5, 0.5, 0.5, 1)
end
-- Create invisible full-screen frame to catch clicks outside bag
if not clickCatcher then
clickCatcher = CreateFrame("Frame", "Guda_ClickCatcher", UIParent)
clickCatcher:SetFrameStrata("BACKGROUND")
clickCatcher:SetAllPoints(UIParent)
clickCatcher:EnableMouse(true)
clickCatcher:Hide()
clickCatcher:SetScript("OnMouseDown", function()
local searchBox = getglobal("Guda_BagFrame_SearchBar_SearchBox")
if searchBox then
searchBox:ClearFocus()
end
end)
end
addon:Debug("Bag frame loaded")
end
-- OnShow
function Guda_BagFrame_OnShow(self)
-- Restore saved position if it exists (only if saved as BOTTOMRIGHT)
if addon and addon.Modules and addon.Modules.DB then
local pos = addon.Modules.DB:GetSetting("bagFramePosition")
if pos and pos.point == "BOTTOMRIGHT" and pos.x and pos.y then
self:ClearAllPoints()
self:SetPoint("BOTTOMRIGHT", "UIParent", "BOTTOMRIGHT", pos.x, pos.y)
end
end
-- Set lock state when frame is shown (ensures all child frames are loaded)
if BagFrame.UpdateLockState then
BagFrame:UpdateLockState()
end
BagFrame:Update()
end
-- OnHide
function Guda_BagFrame_OnHide(self)
-- Release buttons
Guda_ReleaseAllButtons()
end
-- Toggle visibility
function BagFrame:Toggle()
if Guda_BagFrame:IsShown() then
Guda_BagFrame:Hide()
else
Guda_BagFrame:Show()
end
end
-- Show specific character's bags
function BagFrame:ShowCharacter(fullName)
currentViewChar = fullName
self:Update()
end
-- Show current character
function BagFrame:ShowCurrentCharacter()
currentViewChar = nil
self:Update()
end
-- Update display
function BagFrame:Update()
if not Guda_BagFrame:IsShown() then
return
end
-- Clear existing buttons
Guda_ReleaseAllButtons()
local bagData
local isOtherChar = false
local charName = ""
local titleFont = getglobal("Guda_BagFrame_Toolbar_Title")
local displayName
if currentViewChar then
-- Viewing another character
bagData = addon.Modules.DB:GetCharacterBags(currentViewChar)
isOtherChar = true
charName = currentViewChar
local dash = string.find(currentViewChar, "-")
if dash then
displayName = string.sub(currentViewChar, 1, dash - 1)
else
displayName = currentViewChar
end
else
-- Viewing current character
bagData = addon.Modules.BagScanner:ScanBags()
displayName = UnitName("player") or "Character"
end
if titleFont and displayName then
titleFont:SetText(string.format("%s's Bags", displayName))
end
-- Display items
self:DisplayItems(bagData, isOtherChar, charName)
-- Update money
self:UpdateMoney()
end
-- Display items
function BagFrame:DisplayItems(bagData, isOtherChar, charName)
local x, y = 10, -10
local row = 0
local col = 0
local buttonSize = addon.Modules.DB:GetSetting("iconSize") or addon.Constants.BUTTON_SIZE
local spacing = addon.Constants.BUTTON_SPACING
local perRow = addon.Modules.DB:GetSetting("bagColumns") or 10
local itemContainer = getglobal("Guda_BagFrame_ItemContainer")
for _, bagID in ipairs(addon.Constants.BAGS) do
-- Get slot count for this bag
local numSlots = addon.Modules.Utils:GetBagSlotCount(bagID)
-- Only show bags that have slots
if numSlots and numSlots > 0 then
local bag = bagData[bagID]
-- Iterate through ALL slots (1 to numSlots) to show empty slots too
for slot = 1, numSlots do
local itemData = bag and bag.slots and bag.slots[slot] or nil
-- Check if item matches search filter
local matchesFilter = self:PassesSearchFilter(itemData)
local button = Guda_GetItemButton(itemContainer)
-- Position button
local xPos = x + (col * (buttonSize + spacing))
local yPos = y - (row * (buttonSize + spacing))
button:ClearAllPoints()
button:SetPoint("TOPLEFT", itemContainer, "TOPLEFT", xPos, yPos)
-- Set item data with filter match info
Guda_ItemButton_SetItem(button, bagID, slot, itemData, false, isOtherChar and charName or nil, matchesFilter)
table.insert(itemButtons, button)
-- Advance position
col = col + 1
if col >= perRow then
col = 0
row = row + 1
end
end
end
end
-- Resize frame dynamically based on content
self:ResizeFrame(row, col, perRow)
end
-- Resize frame based on number of rows and columns
function BagFrame:ResizeFrame(currentRow, currentCol, columns)
local buttonSize = addon.Modules.DB:GetSetting("iconSize") or addon.Constants.BUTTON_SIZE
local spacing = addon.Constants.BUTTON_SPACING
-- Calculate actual number of rows used
local totalRows = currentRow + 1
-- Ensure at least 1 row
if totalRows < 1 then
totalRows = 1
end
-- Calculate required dimensions based on columns
local containerWidth = (columns * (buttonSize + spacing)) + 20
local containerHeight = (totalRows * (buttonSize + spacing)) + 20
local frameWidth = containerWidth + 30
local frameHeight = containerHeight + 160
-- Minimum sizes
if containerWidth < 200 then
containerWidth = 200
frameWidth = 230
end
if containerHeight < 150 then
containerHeight = 150
end
if frameHeight < 350 then
frameHeight = 350
end
-- Maximum sizes
if containerWidth > 800 then
containerWidth = 800
frameWidth = 830
end
if containerHeight > 600 then
containerHeight = 600
end
if frameHeight > 800 then
frameHeight = 800
end
-- Resize frames
local bagFrame = getglobal("Guda_BagFrame")
local itemContainer = getglobal("Guda_BagFrame_ItemContainer")
if bagFrame then
bagFrame:SetWidth(frameWidth)
bagFrame:SetHeight(frameHeight)
-- Always use BOTTOMRIGHT anchor to make frame grow left
bagFrame:ClearAllPoints()
if addon and addon.Modules and addon.Modules.DB then
local pos = addon.Modules.DB:GetSetting("bagFramePosition")
-- Only use saved position if it was saved as BOTTOMRIGHT
if pos and pos.point == "BOTTOMRIGHT" and pos.x and pos.y then
bagFrame:SetPoint("BOTTOMRIGHT", "UIParent", "BOTTOMRIGHT", pos.x, pos.y)
else
-- Default position: bottom right corner
bagFrame:SetPoint("BOTTOMRIGHT", UIParent, "BOTTOMRIGHT", -50, 100)
end
else
-- Fallback to default if DB not available
bagFrame:SetPoint("BOTTOMRIGHT", UIParent, "BOTTOMRIGHT", -50, 100)
end
end
if itemContainer then
itemContainer:SetWidth(containerWidth)
itemContainer:SetHeight(containerHeight)
end
-- Resize search bar and toolbar to match container width
local searchBar = getglobal("Guda_BagFrame_SearchBar")
if searchBar then
searchBar:SetWidth(containerWidth)
end
local toolbar = getglobal("Guda_BagFrame_Toolbar")
if toolbar then
toolbar:SetWidth(containerWidth)
end
end
-- Check if search is currently active
function BagFrame:IsSearchActive()
return searchText and searchText ~= "" and searchText ~= "Search, try ~equipment"
end
-- Check if item passes search filter (pfUI style)
function BagFrame:PassesSearchFilter(itemData)
-- If no search text, everything matches
if not self:IsSearchActive() then
return true
end
-- Empty slots don't match when searching (pfUI style - they get dimmed)
if not itemData then
return false
end
-- Get item name from itemData.name or parse from link
local itemName = itemData.name
if not itemName and itemData.link then
-- Parse name from item link: |cffffffff|Hitem:...|h[Item Name]|h|r
local _, _, name = string.find(itemData.link, "%[(.+)%]")
itemName = name
if not self.warnedAboutParsing then
addon:Print("DEBUG: Had to parse item name from link: " .. (itemName or "FAILED"))
self.warnedAboutParsing = true
end
end
if not itemName then
if not self.warnedAboutNoName then
addon:Print("DEBUG: Item has no name and no link! texture = " .. tostring(itemData.texture))
self.warnedAboutNoName = true
end
return false
end
-- Case-insensitive search in item name
itemName = string.lower(itemName)
local search = string.lower(searchText)
-- Check if item name contains search text
local matches = string.find(itemName, search, 1, true) ~= nil
-- Debug: print first match found
if matches and not self.foundFirstMatch then
addon:Print("DEBUG: Found match! Item: '" .. itemName .. "' matches search: '" .. searchText .. "'")
self.foundFirstMatch = true
end
return matches
end
-- Update money display
function BagFrame:UpdateMoney()
local currentMoney = addon.Modules.MoneyTracker:GetCurrentMoney()
local moneyFrame = getglobal("Guda_BagFrame_MoneyFrame")
-- Current character money only
if not moneyFrame.text then
moneyFrame.text = moneyFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
moneyFrame.text:SetPoint("CENTER", moneyFrame, "CENTER", 0, 0)
end
moneyFrame.text:SetText(addon.Modules.Utils:FormatMoney(currentMoney))
end
-- Money tooltip handler
function Guda_BagFrame_MoneyOnEnter(self)
GameTooltip:SetOwner(self, "ANCHOR_TOP")
GameTooltip:ClearLines()
-- Get all characters and total
local chars = addon.Modules.DB:GetAllCharacters(true)
local totalMoney = addon.Modules.DB:GetTotalMoney(true)
local currentPlayerName = addon.Modules.DB:GetPlayerFullName()
-- Header with faction/realm total
GameTooltip:AddLine("Faction/realm-wide gold:", 1, 0.82, 0, 1)
GameTooltip:AddLine(addon.Modules.Utils:FormatMoney(totalMoney), 1, 1, 1, 1)
GameTooltip:AddLine(" ")
-- List each character
for _, char in ipairs(chars) do
local colorR, colorG, colorB = 0.7, 0.7, 0.7
-- Highlight current character
if char.fullName == currentPlayerName then
colorR, colorG, colorB = 0, 1, 0.6
end
GameTooltip:AddDoubleLine(
char.name,
addon.Modules.Utils:FormatMoney(char.money or 0),
colorR, colorG, colorB,
1, 1, 1
)
end
GameTooltip:Show()
end
-- Search changed handler
function Guda_BagFrame_OnSearchChanged(self)
local text = self:GetText()
-- Ignore placeholder text
if text == "Search, try ~equipment" then
text = ""
end
if text ~= searchText then
searchText = text
BagFrame.foundFirstMatch = false -- Reset debug flags
BagFrame.warnedAboutParsing = false
BagFrame.warnedAboutNoName = false
addon:Print("Search text changed to: '" .. (searchText or "empty") .. "'")
BagFrame:Update()
end
end
-- Sort button handler
function Guda_BagFrame_Sort()
if currentViewChar then
addon:Print("Cannot sort another character's bags!")
return
end
addon.Modules.SortEngine:SortBags()
-- Update after a delay to allow items to move
local frame = CreateFrame("Frame")
local elapsed = 0
frame:SetScript("OnUpdate", function()
elapsed = elapsed + arg1
if elapsed >= 0.5 then
frame:SetScript("OnUpdate", nil)
BagFrame:Update()
end
end)
end
-- Hook to default bag opening
local function HookDefaultBags()
-- Override ToggleBackpack
local originalToggleBackpack = ToggleBackpack
function ToggleBackpack()
BagFrame:Toggle()
end
-- Override OpenAllBags
local originalOpenAllBags = OpenAllBags
function OpenAllBags()
Guda_BagFrame:Show()
end
-- Override CloseAllBags
local originalCloseAllBags = CloseAllBags
function CloseAllBags()
Guda_BagFrame:Hide()
end
end
-- Save bag frame position (always as BOTTOMRIGHT)
local function SaveBagFramePosition()
local frame = getglobal("Guda_BagFrame")
if not frame or not addon or not addon.Modules or not addon.Modules.DB then return end
-- Always save as BOTTOMRIGHT coordinates
local right = frame:GetRight()
local bottom = frame:GetBottom()
local screenWidth = GetScreenWidth()
if right and bottom and screenWidth then
local xOffset = right - screenWidth
local yOffset = bottom
addon.Modules.DB:SetSetting("bagFramePosition", {
point = "BOTTOMRIGHT",
x = xOffset,
y = yOffset
})
end
end
-- Update lock state (controls whether frame is draggable)
function BagFrame:UpdateLockState()
-- Safety check: ensure addon and modules exist
if not addon or not addon.Modules then return end
local frame = getglobal("Guda_BagFrame")
if not frame then return end
-- Check if DB module is available
if not addon.Modules.DB or not addon.Modules.DB.GetSetting then return end
local success, isLocked = pcall(function()
return addon.Modules.DB:GetSetting("lockBags")
end)
if not success then return end
if isLocked == nil then
isLocked = false
end
-- Get draggable areas
local toolbar = getglobal("Guda_BagFrame_Toolbar")
local moneyFrame = getglobal("Guda_BagFrame_MoneyFrame")
local itemContainer = getglobal("Guda_BagFrame_ItemContainer")
if isLocked then
-- Disable dragging on main frame
if frame.SetScript then
frame:SetScript("OnMouseDown", function()
local searchBox = getglobal("Guda_BagFrame_SearchBar_SearchBox")
if searchBox then
searchBox:ClearFocus()
end
end)
frame:SetScript("OnMouseUp", nil)
end
-- Disable dragging on toolbar
if toolbar and toolbar.SetScript then
toolbar:SetScript("OnMouseDown", function()
local searchBox = getglobal("Guda_BagFrame_SearchBar_SearchBox")
if searchBox then
searchBox:ClearFocus()
end
end)
toolbar:SetScript("OnMouseUp", nil)
end
-- Disable dragging on money frame (preserve tooltip handlers)
if moneyFrame and moneyFrame.SetScript then
moneyFrame:SetScript("OnMouseDown", function()
local searchBox = getglobal("Guda_BagFrame_SearchBar_SearchBox")
if searchBox then
searchBox:ClearFocus()
end
end)
moneyFrame:SetScript("OnMouseUp", nil)
-- Preserve tooltip handlers with safety checks
moneyFrame:SetScript("OnEnter", function()
if Guda_BagFrame_MoneyOnEnter and addon and addon.Modules and addon.Modules.DB and addon.Modules.Utils then
Guda_BagFrame_MoneyOnEnter(this)
end
end)
moneyFrame:SetScript("OnLeave", function()
if GameTooltip then
GameTooltip:Hide()
end
end)
end
-- Disable dragging on item container
if itemContainer and itemContainer.SetScript then
itemContainer:SetScript("OnMouseDown", function()
local searchBox = getglobal("Guda_BagFrame_SearchBar_SearchBox")
if searchBox then
searchBox:ClearFocus()
end
end)
itemContainer:SetScript("OnMouseUp", nil)
end
else
-- Enable dragging on main frame
if frame and frame.SetScript then
frame:SetScript("OnMouseDown", function()
local searchBox = getglobal("Guda_BagFrame_SearchBar_SearchBox")
if searchBox then
searchBox:ClearFocus()
end
local bagFrame = getglobal("Guda_BagFrame")
if bagFrame and arg1 == "LeftButton" then
bagFrame:StartMoving()
end
end)
frame:SetScript("OnMouseUp", function()
local bagFrame = getglobal("Guda_BagFrame")
if bagFrame then
bagFrame:StopMovingOrSizing()
SaveBagFramePosition()
end
end)
end
-- Enable dragging on toolbar (title area)
if toolbar and toolbar.SetScript then
toolbar:SetScript("OnMouseDown", function()
local searchBox = getglobal("Guda_BagFrame_SearchBar_SearchBox")
if searchBox then
searchBox:ClearFocus()
end
local bagFrame = getglobal("Guda_BagFrame")
if bagFrame and arg1 == "LeftButton" then
bagFrame:StartMoving()
end
end)
toolbar:SetScript("OnMouseUp", function()
local bagFrame = getglobal("Guda_BagFrame")
if bagFrame then
bagFrame:StopMovingOrSizing()
SaveBagFramePosition()
end
end)
end
-- Enable dragging on money frame (preserve tooltip handlers)
if moneyFrame and moneyFrame.SetScript then
moneyFrame:SetScript("OnMouseDown", function()
local searchBox = getglobal("Guda_BagFrame_SearchBar_SearchBox")
if searchBox then
searchBox:ClearFocus()
end
local bagFrame = getglobal("Guda_BagFrame")
if bagFrame and arg1 == "LeftButton" then
bagFrame:StartMoving()
end
end)
moneyFrame:SetScript("OnMouseUp", function()
local bagFrame = getglobal("Guda_BagFrame")
if bagFrame then
bagFrame:StopMovingOrSizing()
SaveBagFramePosition()
end
end)
-- Preserve tooltip handlers with safety checks
moneyFrame:SetScript("OnEnter", function()
if Guda_BagFrame_MoneyOnEnter and addon and addon.Modules and addon.Modules.DB and addon.Modules.Utils then
Guda_BagFrame_MoneyOnEnter(this)
end
end)
moneyFrame:SetScript("OnLeave", function()
if GameTooltip then
GameTooltip:Hide()
end
end)
end
-- Enable dragging on item container
if itemContainer and itemContainer.SetScript then
itemContainer:SetScript("OnMouseDown", function()
local searchBox = getglobal("Guda_BagFrame_SearchBar_SearchBox")
if searchBox then
searchBox:ClearFocus()
end
local bagFrame = getglobal("Guda_BagFrame")
if bagFrame and arg1 == "LeftButton" then
bagFrame:StartMoving()
end
end)
itemContainer:SetScript("OnMouseUp", function()
local bagFrame = getglobal("Guda_BagFrame")
if bagFrame then
bagFrame:StopMovingOrSizing()
SaveBagFramePosition()
end
end)
end
end
end
-- Initialize
function BagFrame:Initialize()
-- Hook default bag functions
HookDefaultBags()
-- Update on bag changes
addon.Modules.Events:OnBagUpdate(function()
if not currentViewChar then
BagFrame:Update()
end
end, "BagFrame")
-- Update on money changes
addon.Modules.Events:OnMoneyChanged(function()
BagFrame:UpdateMoney()
end, "BagFrame")
addon:Debug("Bag frame initialized")
end
+313
View File
@@ -0,0 +1,313 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/">
<!-- Main Bag Frame -->
<Frame name="Guda_BagFrame" toplevel="true" movable="true" enableMouse="true" hidden="true" parent="UIParent">
<Size>
<AbsDimension x="420" y="600"/>
</Size>
<Anchors>
<Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT" relativeTo="UIParent">
<Offset>
<AbsDimension x="-50" y="100"/>
</Offset>
</Anchor>
</Anchors>
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\DialogFrame\UI-DialogBox-Border" tile="true">
<BackgroundInsets>
<AbsInset left="11" right="12" top="12" bottom="11"/>
</BackgroundInsets>
<TileSize>
<AbsValue val="16"/>
</TileSize>
<EdgeSize>
<AbsValue val="32"/>
</EdgeSize>
<Color r="0" g="0" b="0" a="0.9"/>
</Backdrop>
<!-- Keep a (currently unused) top-level layer block for future use -->
<Layers>
<Layer level="BACKGROUND"/>
</Layers>
<Frames>
<!-- Close Button -->
<Button name="$parent_CloseButton" inherits="UIPanelCloseButton">
<Anchors>
<Anchor point="TOPRIGHT" x="-5" y="-5"/>
</Anchors>
<Scripts>
<OnClick>
Guda_BagFrame:Hide()
</OnClick>
</Scripts>
</Button>
<!-- Toolbar Container (top row) -->
<Frame name="$parent_Toolbar" enableMouse="true">
<Size>
<AbsDimension x="400" y="30"/>
</Size>
<Anchors>
<Anchor point="TOP" x="0" y="-10"/>
</Anchors>
<Scripts>
<OnMouseDown>
-- Clear search focus when clicking toolbar
local searchBox = getglobal("Guda_BagFrame_SearchBar_SearchBox")
if searchBox then
searchBox:ClearFocus()
end
</OnMouseDown>
</Scripts>
<!-- Title centered in toolbar -->
<Layers>
<Layer level="ARTWORK">
<FontString name="$parent_Title" inherits="GameFontNormalLarge">
<Anchors>
<Anchor point="CENTER" x="0" y="0"/>
</Anchors>
</FontString>
</Layer>
</Layers>
<Frames>
<!-- Sort Button -->
<Button name="$parent_SortButton">
<Size>
<AbsDimension x="24" y="24"/>
</Size>
<Anchors>
<Anchor point="LEFT" x="10" y="0"/>
</Anchors>
<NormalTexture file="Interface\\Icons\\INV_Misc_Note_01"/>
<Scripts>
<OnClick>
Guda_BagFrame_Sort()
</OnClick>
<OnEnter>
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
GameTooltip:SetText("Sort Bags")
GameTooltip:Show()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
</Scripts>
</Button>
<!-- Characters Button -->
<Button name="$parent_CharsButton">
<Size>
<AbsDimension x="24" y="24"/>
</Size>
<Anchors>
<Anchor point="LEFT" relativePoint="RIGHT" relativeTo="$parent_SortButton" x="5" y="0"/>
</Anchors>
<NormalTexture file="Interface\\Icons\\INV_Misc_GroupNeedMore"/>
<Scripts>
<OnClick>
Guda_CharacterSelector:Toggle()
</OnClick>
<OnEnter>
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
GameTooltip:SetText("View Other Characters")
GameTooltip:Show()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
</Scripts>
</Button>
<!-- Bank Button -->
<Button name="$parent_BankButton">
<Size>
<AbsDimension x="24" y="24"/>
</Size>
<Anchors>
<Anchor point="LEFT" relativePoint="RIGHT" relativeTo="$parent_CharsButton" x="5" y="0"/>
</Anchors>
<NormalTexture file="Interface\\Icons\\INV_Misc_Bag_09"/>
<Scripts>
<OnClick>
Guda_BankFrame:Toggle()
</OnClick>
<OnEnter>
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
GameTooltip:SetText("View Bank")
GameTooltip:Show()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
</Scripts>
</Button>
<!-- Settings Button -->
<Button name="$parent_SettingsButton">
<Size>
<AbsDimension x="24" y="24"/>
</Size>
<Anchors>
<Anchor point="LEFT" relativePoint="RIGHT" relativeTo="$parent_BankButton" x="5" y="0"/>
</Anchors>
<NormalTexture file="Interface\\Icons\\Trade_Engineering"/>
<Scripts>
<OnClick>
Guda_OpenSettings()
</OnClick>
<OnEnter>
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
GameTooltip:SetText("Settings")
GameTooltip:Show()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
</Scripts>
</Button>
</Frames>
</Frame>
<!-- Search Bar (second row) -->
<Frame name="$parent_SearchBar">
<Size>
<AbsDimension x="400" y="30"/>
</Size>
<Anchors>
<Anchor point="TOP" relativePoint="BOTTOM" relativeTo="$parent_Toolbar" x="0" y="-5"/>
</Anchors>
<Frames>
<!-- Full-width Search Box -->
<EditBox name="$parent_SearchBox" autoFocus="false" inherits="InputBoxTemplate">
<Size>
<AbsDimension x="0" y="20"/>
</Size>
<Anchors>
<Anchor point="LEFT" x="10" y="0"/>
<Anchor point="RIGHT" x="-10" y="0"/>
</Anchors>
<Scripts>
<OnEditFocusGained>
if this:GetText() == "Search, try ~equipment" then
this:SetText("")
this:SetTextColor(1, 1, 1, 1)
end
-- Show click catcher to detect clicks outside bag
local clickCatcher = getglobal("Guda_ClickCatcher")
if clickCatcher then clickCatcher:Show() end
</OnEditFocusGained>
<OnEditFocusLost>
-- Hide click catcher when focus is lost
local clickCatcher = getglobal("Guda_ClickCatcher")
if clickCatcher then clickCatcher:Hide() end
-- Restore placeholder if empty when focus is lost
if this:GetText() == "" then
this:SetText("Search, try ~equipment")
this:SetTextColor(0.5, 0.5, 0.5, 1)
Guda_BagFrame_OnSearchChanged(this)
end
</OnEditFocusLost>
<OnTextChanged>
Guda_BagFrame_OnSearchChanged(this)
</OnTextChanged>
<OnEscapePressed>
this:SetText("Search, try ~equipment")
this:SetTextColor(0.5, 0.5, 0.5, 1)
this:ClearFocus()
Guda_BagFrame_OnSearchChanged(this)
</OnEscapePressed>
</Scripts>
</EditBox>
</Frames>
</Frame>
<!-- Money Display Frame -->
<Frame name="$parent_MoneyFrame" enableMouse="true">
<Size>
<AbsDimension x="300" y="30"/>
</Size>
<Anchors>
<Anchor point="BOTTOM" x="0" y="10"/>
</Anchors>
<Scripts>
<OnMouseDown>
-- Clear search focus when clicking money area
local searchBox = getglobal("Guda_BagFrame_SearchBar_SearchBox")
if searchBox then
searchBox:ClearFocus()
end
</OnMouseDown>
<OnEnter>
Guda_BagFrame_MoneyOnEnter(this)
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
</Scripts>
</Frame>
<!-- Container for item buttons -->
<Frame name="$parent_ItemContainer" enableMouse="true">
<Size>
<AbsDimension x="390" y="480"/>
</Size>
<Anchors>
<Anchor point="TOP" relativePoint="BOTTOM" relativeTo="$parent_SearchBar" x="0" y="-5"/>
</Anchors>
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" tile="true">
<BackgroundInsets>
<AbsInset left="0" right="0" top="0" bottom="0"/>
</BackgroundInsets>
<TileSize>
<AbsValue val="16"/>
</TileSize>
<Color r="0" g="0" b="0" a="0.5"/>
</Backdrop>
<Scripts>
<OnMouseDown>
-- Clear search focus when clicking in item area
local searchBox = getglobal("Guda_BagFrame_SearchBar_SearchBox")
if searchBox then
searchBox:ClearFocus()
end
</OnMouseDown>
</Scripts>
</Frame>
</Frames>
<Scripts>
<OnLoad>
Guda_BagFrame_OnLoad(this)
</OnLoad>
<OnShow>
Guda_BagFrame_OnShow(this)
</OnShow>
<OnHide>
Guda_BagFrame_OnHide(this)
</OnHide>
<OnMouseDown>
-- Clear search box focus when clicking on bag frame (1.12.1 safe)
local searchBox = getglobal("Guda_BagFrame_SearchBar_SearchBox")
if searchBox then
searchBox:ClearFocus()
end
if (arg1 == "LeftButton") then
this:StartMoving()
end
</OnMouseDown>
<OnMouseUp>
this:StopMovingOrSizing()
</OnMouseUp>
</Scripts>
</Frame>
</Ui>
+238
View File
@@ -0,0 +1,238 @@
-- Guda Bank Frame
-- Bank viewing UI
local addon = Guda
local BankFrame = {}
addon.Modules.BankFrame = BankFrame
local currentViewChar = nil
local searchText = ""
-- OnLoad
function Guda_BankFrame_OnLoad(self)
getglobal(self:GetName().."_Title"):SetText("Guda Bank")
getglobal(self:GetName().."_SearchBox"):SetText("Search...")
addon:Debug("Bank frame loaded")
end
-- OnShow
function Guda_BankFrame_OnShow(self)
BankFrame:Update()
end
-- OnHide
function Guda_BankFrame_OnHide(self)
Guda_ReleaseAllButtons()
end
-- Toggle visibility
function BankFrame:Toggle()
if Guda_BankFrame:IsShown() then
Guda_BankFrame:Hide()
else
Guda_BankFrame:Show()
end
end
-- Show specific character's bank
function BankFrame:ShowCharacter(fullName)
currentViewChar = fullName
self:Update()
end
-- Show current character's bank
function BankFrame:ShowCurrentCharacter()
currentViewChar = nil
self:Update()
end
-- Update display
function BankFrame:Update()
if not Guda_BankFrame:IsShown() then
return
end
Guda_ReleaseAllButtons()
local bankData
local isOtherChar = false
local charName = ""
if currentViewChar then
bankData = addon.Modules.DB:GetCharacterBank(currentViewChar)
isOtherChar = true
charName = currentViewChar
getglobal("Guda_BankFrame_Title"):SetText("Bank - " .. currentViewChar)
else
bankData = addon.Modules.DB:GetCharacterBank(addon.Modules.DB:GetPlayerFullName())
if not bankData or not next(bankData) then
-- No saved bank data, use live scan if bank is open
if addon.Modules.BankScanner:IsBankOpen() then
bankData = addon.Modules.BankScanner:ScanBank()
end
end
getglobal("Guda_BankFrame_Title"):SetText("Guda Bank")
end
self:DisplayItems(bankData, isOtherChar, charName)
end
-- Display items
function BankFrame:DisplayItems(bankData, isOtherChar, charName)
local x, y = 10, -10
local row = 0
local col = 0
local buttonSize = addon.Modules.DB:GetSetting("iconSize") or addon.Constants.BUTTON_SIZE
local spacing = addon.Constants.BUTTON_SPACING
local perRow = addon.Modules.DB:GetSetting("bankColumns") or 15
local itemContainer = getglobal("Guda_BankFrame_ItemContainer")
for _, bagID in ipairs(addon.Constants.BANK_BAGS) do
local bag = bankData[bagID]
if bag and bag.slots then
for slot, itemData in pairs(bag.slots) do
if self:PassesSearchFilter(itemData) then
local button = Guda_GetItemButton(itemContainer)
local xPos = x + (col * (buttonSize + spacing))
local yPos = y - (row * (buttonSize + spacing))
button:ClearAllPoints()
button:SetPoint("TOPLEFT", itemContainer, "TOPLEFT", xPos, yPos)
Guda_ItemButton_SetItem(button, bagID, slot, itemData, true, isOtherChar and charName or nil)
col = col + 1
if col >= perRow then
col = 0
row = row + 1
end
end
end
end
end
-- Resize frame dynamically based on content
self:ResizeFrame(row, col, perRow)
end
-- Resize bank frame based on number of rows and columns
function BankFrame:ResizeFrame(currentRow, currentCol, columns)
local buttonSize = addon.Modules.DB:GetSetting("iconSize") or addon.Constants.BUTTON_SIZE
local spacing = addon.Constants.BUTTON_SPACING
-- Calculate actual number of rows used
local totalRows = currentRow + 1
if totalRows < 1 then
totalRows = 1
end
-- Ensure at least 1 column
if not columns or columns < 1 then
columns = 1
end
-- Calculate required dimensions
local containerWidth = (columns * (buttonSize + spacing)) + 20
local containerHeight = (totalRows * (buttonSize + spacing)) + 20
local frameWidth = containerWidth + 30
local frameHeight = containerHeight + 120
-- Minimum sizes
if containerWidth < 200 then
containerWidth = 200
frameWidth = 230
end
if containerHeight < 150 then
containerHeight = 150
end
if frameHeight < 350 then
frameHeight = 350
end
-- Maximum sizes
if containerWidth > 800 then
containerWidth = 800
frameWidth = 830
end
if containerHeight > 600 then
containerHeight = 600
end
if frameHeight > 800 then
frameHeight = 800
end
local bankFrame = getglobal("Guda_BankFrame")
local itemContainer = getglobal("Guda_BankFrame_ItemContainer")
if bankFrame then
bankFrame:SetWidth(frameWidth)
bankFrame:SetHeight(frameHeight)
end
if itemContainer then
itemContainer:SetWidth(containerWidth)
itemContainer:SetHeight(containerHeight)
end
end
-- Check if item passes search filter
function BankFrame:PassesSearchFilter(itemData)
if searchText == "" or searchText == "Search..." then
return true
end
if not itemData or not itemData.name then
return false
end
return string.find(string.lower(itemData.name), string.lower(searchText)) ~= nil
end
-- Search changed handler
function Guda_BankFrame_OnSearchChanged(self)
local text = self:GetText()
if text ~= searchText then
searchText = text
BankFrame:Update()
end
end
-- Sort button handler
function Guda_BankFrame_Sort()
if currentViewChar then
addon:Print("Cannot sort another character's bank!")
return
end
addon.Modules.SortEngine:SortBank()
local frame = CreateFrame("Frame")
local elapsed = 0
frame:SetScript("OnUpdate", function()
elapsed = elapsed + arg1
if elapsed >= 0.5 then
frame:SetScript("OnUpdate", nil)
BankFrame:Update()
end
end)
end
-- Initialize
function BankFrame:Initialize()
-- Update when bank is opened
addon.Modules.Events:OnBankOpen(function()
BankFrame:Update()
end, "BankFrameUI")
-- Update on bag changes while bank is open
addon.Modules.Events:OnBagUpdate(function()
if addon.Modules.BankScanner:IsBankOpen() and not currentViewChar then
BankFrame:Update()
end
end, "BankFrameUI")
addon:Debug("Bank frame initialized")
end
+142
View File
@@ -0,0 +1,142 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/">
<!-- Bank Frame -->
<Frame name="Guda_BankFrame" toplevel="true" movable="true" enableMouse="true" hidden="true" parent="UIParent">
<Size>
<AbsDimension x="400" y="500"/>
</Size>
<Anchors>
<Anchor point="LEFT" relativePoint="LEFT" relativeTo="UIParent">
<Offset>
<AbsDimension x="50" y="0"/>
</Offset>
</Anchor>
</Anchors>
<Backdrop bgFile="Interface\DialogFrame\UI-DialogBox-Background" edgeFile="Interface\DialogFrame\UI-DialogBox-Border" tile="true">
<BackgroundInsets>
<AbsInset left="11" right="12" top="12" bottom="11"/>
</BackgroundInsets>
<TileSize>
<AbsValue val="32"/>
</TileSize>
<EdgeSize>
<AbsValue val="32"/>
</EdgeSize>
</Backdrop>
<Layers>
<!-- Title -->
<Layer level="ARTWORK">
<FontString name="$parent_Title" inherits="GameFontNormalLarge">
<Anchors>
<Anchor point="TOP" x="0" y="-15"/>
</Anchors>
</FontString>
</Layer>
</Layers>
<Frames>
<!-- Close Button -->
<Button name="$parent_CloseButton" inherits="UIPanelCloseButton">
<Anchors>
<Anchor point="TOPRIGHT" x="-5" y="-5"/>
</Anchors>
<Scripts>
<OnClick>
Guda_BankFrame:Hide()
</OnClick>
</Scripts>
</Button>
<!-- Settings Button -->
<Button name="$parent_SettingsButton">
<Size>
<AbsDimension x="24" y="24"/>
</Size>
<Anchors>
<Anchor point="TOPRIGHT" relativePoint="TOPLEFT" relativeTo="$parent_CloseButton" x="-5" y="0"/>
</Anchors>
<NormalTexture file="Interface\Icons\Trade_Engineering"/>
<Scripts>
<OnClick>
Guda_OpenSettings()
</OnClick>
<OnEnter>
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
GameTooltip:SetText("Settings")
GameTooltip:Show()
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
</Scripts>
</Button>
<!-- Search Box -->
<EditBox name="$parent_SearchBox" autoFocus="false" inherits="InputBoxTemplate">
<Size>
<AbsDimension x="200" y="20"/>
</Size>
<Anchors>
<Anchor point="TOP" x="0" y="-45"/>
</Anchors>
<Scripts>
<OnTextChanged>
Guda_BankFrame_OnSearchChanged(this)
</OnTextChanged>
<OnEscapePressed>
this:ClearFocus()
</OnEscapePressed>
</Scripts>
</EditBox>
<!-- Sort Button -->
<Button name="$parent_SortButton" inherits="UIPanelButtonTemplate" text="Sort Bank">
<Size>
<AbsDimension x="100" y="22"/>
</Size>
<Anchors>
<Anchor point="BOTTOM" x="0" y="10"/>
</Anchors>
<Scripts>
<OnClick>
Guda_BankFrame_Sort()
</OnClick>
</Scripts>
</Button>
<!-- Container for item buttons -->
<Frame name="$parent_ItemContainer">
<Size>
<AbsDimension x="370" y="420"/>
</Size>
<Anchors>
<Anchor point="TOP" x="0" y="-75"/>
</Anchors>
</Frame>
</Frames>
<Scripts>
<OnLoad>
Guda_BankFrame_OnLoad(this)
</OnLoad>
<OnShow>
Guda_BankFrame_OnShow(this)
</OnShow>
<OnHide>
Guda_BankFrame_OnHide(this)
</OnHide>
<OnMouseDown>
if (arg1 == "LeftButton") then
this:StartMoving()
end
</OnMouseDown>
<OnMouseUp>
this:StopMovingOrSizing()
</OnMouseUp>
</Scripts>
</Frame>
</Ui>
+128
View File
@@ -0,0 +1,128 @@
-- Guda Character Selector
-- Select character to view bags/bank
local addon = Guda
local CharacterSelector = {}
addon.Modules.CharacterSelector = CharacterSelector
local charButtons = {}
-- OnLoad
function Guda_CharacterSelector_OnLoad(self)
getglobal(self:GetName().."_Title"):SetText("Select Character")
addon:Debug("Character selector loaded")
end
-- OnShow
function Guda_CharacterSelector_OnShow(self)
CharacterSelector:Update()
end
-- Toggle visibility
function CharacterSelector:Toggle()
if Guda_CharacterSelector:IsShown() then
Guda_CharacterSelector:Hide()
else
Guda_CharacterSelector:Show()
end
end
-- Update character list
function CharacterSelector:Update()
-- Clear existing buttons
for _, button in ipairs(charButtons) do
button:Hide()
end
charButtons = {}
-- Get all characters
local characters = addon.Modules.DB:GetAllCharacters(true) -- Same faction only
local characterList = getglobal("Guda_CharacterSelector_CharacterList")
-- Create buttons for each character
local yOffset = -10
for i, char in ipairs(characters) do
local button = self:GetCharacterButton(i)
-- Set text with class color
local classColor = addon.Modules.Utils:GetClassColor(char.class)
local coloredName = addon.Modules.Utils:ColorText(char.name, classColor.r, classColor.g, classColor.b)
button:SetText(string.format("%s (Lv %d)", coloredName, char.level))
button.charData = char
-- Position
button:ClearAllPoints()
button:SetPoint("TOP", characterList, "TOP", 0, yOffset)
yOffset = yOffset - 35
button:Show()
table.insert(charButtons, button)
end
if table.getn(characters) == 0 then
addon:Debug("No other characters found")
end
end
-- Get or create character button
function CharacterSelector:GetCharacterButton(index)
local name = "Guda_CharButton" .. index
local characterList = getglobal("Guda_CharacterSelector_CharacterList")
local button = getglobal(name)
if not button then
button = CreateFrame("Button", name, characterList, "Guda_CharacterButtonTemplate")
end
return button
end
-- Character button OnClick
function Guda_CharacterButton_OnClick(self)
if not self.charData then
return
end
addon:Print("Viewing %s's bags", self.charData.name)
-- Show bags for this character
addon.Modules.BagFrame:ShowCharacter(self.charData.fullName)
-- Close selector
Guda_CharacterSelector:Hide()
-- Show bag frame if not visible
if not Guda_BagFrame:IsShown() then
Guda_BagFrame:Show()
end
end
-- Character button OnEnter
function Guda_CharacterButton_OnEnter(self)
if not self.charData then
return
end
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
GameTooltip:AddLine(self.charData.name, 1, 1, 1)
GameTooltip:AddLine("Level " .. self.charData.level .. " " .. self.charData.class, 0.7, 0.7, 0.7)
GameTooltip:AddLine("Money: " .. addon.Modules.Utils:FormatMoney(self.charData.money))
if self.charData.lastUpdate then
GameTooltip:AddLine("Last seen: " .. addon.Modules.Utils:FormatTimeAgo(self.charData.lastUpdate), 0.5, 0.5, 0.5)
end
GameTooltip:Show()
end
-- Show current character
function Guda_CharacterSelector_ShowCurrent()
addon.Modules.BagFrame:ShowCurrentCharacter()
Guda_CharacterSelector:Hide()
if not Guda_BagFrame:IsShown() then
Guda_BagFrame:Show()
end
end
+115
View File
@@ -0,0 +1,115 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/">
<!-- Character Button Template -->
<Button name="Guda_CharacterButtonTemplate" virtual="true" inherits="UIPanelButtonTemplate">
<Size>
<AbsDimension x="240" y="30"/>
</Size>
<Scripts>
<OnClick>
Guda_CharacterButton_OnClick(this)
</OnClick>
<OnEnter>
Guda_CharacterButton_OnEnter(this)
</OnEnter>
<OnLeave>
GameTooltip:Hide()
</OnLeave>
</Scripts>
</Button>
<!-- Character Selector Frame -->
<Frame name="Guda_CharacterSelector" toplevel="true" movable="true" enableMouse="true" hidden="true" parent="UIParent">
<Size>
<AbsDimension x="280" y="400"/>
</Size>
<Anchors>
<Anchor point="CENTER" relativePoint="CENTER" relativeTo="UIParent">
<Offset>
<AbsDimension x="0" y="0"/>
</Offset>
</Anchor>
</Anchors>
<Backdrop bgFile="Interface\DialogFrame\UI-DialogBox-Background" edgeFile="Interface\DialogFrame\UI-DialogBox-Border" tile="true">
<BackgroundInsets>
<AbsInset left="11" right="12" top="12" bottom="11"/>
</BackgroundInsets>
<TileSize>
<AbsValue val="32"/>
</TileSize>
<EdgeSize>
<AbsValue val="32"/>
</EdgeSize>
</Backdrop>
<Layers>
<!-- Title -->
<Layer level="ARTWORK">
<FontString name="$parent_Title" inherits="GameFontNormalLarge">
<Anchors>
<Anchor point="TOP" x="0" y="-15"/>
</Anchors>
</FontString>
</Layer>
</Layers>
<Frames>
<!-- Close Button -->
<Button name="$parent_CloseButton" inherits="UIPanelCloseButton">
<Anchors>
<Anchor point="TOPRIGHT" x="-5" y="-5"/>
</Anchors>
<Scripts>
<OnClick>
Guda_CharacterSelector:Hide()
</OnClick>
</Scripts>
</Button>
<!-- Current Character Button -->
<Button name="$parent_CurrentCharButton" inherits="UIPanelButtonTemplate" text="Current Character">
<Size>
<AbsDimension x="240" y="30"/>
</Size>
<Anchors>
<Anchor point="TOP" x="0" y="-45"/>
</Anchors>
<Scripts>
<OnClick>
Guda_CharacterSelector_ShowCurrent()
</OnClick>
</Scripts>
</Button>
<!-- Character List Container -->
<Frame name="$parent_CharacterList">
<Size>
<AbsDimension x="260" y="310"/>
</Size>
<Anchors>
<Anchor point="TOP" x="0" y="-85"/>
</Anchors>
</Frame>
</Frames>
<Scripts>
<OnLoad>
Guda_CharacterSelector_OnLoad(this)
</OnLoad>
<OnShow>
Guda_CharacterSelector_OnShow(this)
</OnShow>
<OnMouseDown>
if (arg1 == "LeftButton") then
this:StartMoving()
end
</OnMouseDown>
<OnMouseUp>
this:StopMovingOrSizing()
</OnMouseUp>
</Scripts>
</Frame>
</Ui>
+318
View File
@@ -0,0 +1,318 @@
-- Guda Item Button
-- Handles item button display and interaction
local addon = Guda
-- Item button pool
local buttonPool = {}
local nextButtonID = 1
-- Create or get a button from the pool
function Guda_GetItemButton(parent)
-- Try to reuse existing button
for _, button in pairs(buttonPool) do
if not button:IsShown() and button:GetParent() == parent then
return button
end
end
-- Create new button
local button = CreateFrame("Button", "Guda_ItemButton" .. nextButtonID, parent, "Guda_ItemButtonTemplate")
buttonPool[nextButtonID] = button
nextButtonID = nextButtonID + 1
return button
end
-- OnLoad handler
function Guda_ItemButton_OnLoad(self)
self.hasItem = false
self.bagID = nil
self.slotID = nil
self.itemData = nil
self.isBank = false
self.otherChar = nil
end
-- Set item data
function Guda_ItemButton_SetItem(self, bagID, slotID, itemData, isBank, otherCharName, matchesFilter)
self.bagID = bagID
self.slotID = slotID
self.itemData = itemData
self.isBank = isBank or false
self.otherChar = otherCharName
-- Default to true if not specified (for non-filtered displays)
if matchesFilter == nil then
matchesFilter = true
end
local countText = getglobal(self:GetName().."_Count")
local qualityBorder = getglobal(self:GetName().."_QualityBorder")
local emptySlotBg = getglobal(self:GetName().."_EmptySlotBg")
-- Apply icon size setting
local iconSize = Guda.Modules.DB:GetSetting("iconSize") or addon.Constants.BUTTON_SIZE
self:SetWidth(iconSize)
self:SetHeight(iconSize)
-- Resize empty slot background to match icon size (slightly larger to ensure coverage)
if emptySlotBg then
emptySlotBg:ClearAllPoints()
emptySlotBg:SetPoint("TOPLEFT", self, "TOPLEFT", -2, 2)
emptySlotBg:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 2, -2)
-- Crop texture edges slightly to remove any built-in padding
emptySlotBg:SetTexCoord(0.1, 0.9, 0.1, 0.9)
end
-- Also resize the underlying slot textures so the border/background scale with the button.
-- On 1.12/Turtle, ItemButtonTemplate uses fixed-size textures, so we explicitly size them
-- to match the current iconSize instead of letting them use their default dimensions.
-- For 1.12.1 compatibility, access textures using both methods and proper naming
-- We'll set the NormalTexture later based on whether slot is empty or filled
-- Pushed texture follows the button size/position
local pushedTexture = getglobal(self:GetName().."PushedTexture")
if not pushedTexture and self.GetPushedTexture then
pushedTexture = self:GetPushedTexture()
end
if pushedTexture then
pushedTexture:ClearAllPoints()
pushedTexture:SetPoint("CENTER", self, "CENTER", 0, 0)
pushedTexture:SetWidth(iconSize)
pushedTexture:SetHeight(iconSize)
end
-- Highlight texture for mouseover (not used for search)
local highlightTexture = getglobal(self:GetName().."HighlightTexture")
if not highlightTexture and self.GetHighlightTexture then
highlightTexture = self:GetHighlightTexture()
end
if highlightTexture then
highlightTexture:ClearAllPoints()
highlightTexture:SetPoint("CENTER", self, "CENTER", 0, 0)
highlightTexture:SetWidth(iconSize)
highlightTexture:SetHeight(iconSize)
end
-- Checked texture (centered square pattern when slot is "active")
local checkedTexture = getglobal(self:GetName().."CheckedTexture")
if not checkedTexture and self.GetCheckedTexture then
checkedTexture = self:GetCheckedTexture()
end
if checkedTexture then
checkedTexture:ClearAllPoints()
checkedTexture:SetPoint("CENTER", self, "CENTER", 0, 0)
checkedTexture:SetWidth(iconSize)
checkedTexture:SetHeight(iconSize)
end
-- Apply icon font size setting to stack count text
if countText and countText.GetFont then
local font, _, flags = countText:GetFont()
local fontSize = Guda.Modules.DB:GetSetting("iconFontSize") or 12
countText:SetFont(font, fontSize, flags)
end
if itemData then
self.hasItem = true
-- Set icon
SetItemButtonTexture(self, itemData.texture)
-- Hide NormalTexture for filled slots (pfUI style)
self:SetNormalTexture("")
local normalBorder = getglobal(self:GetName().."NormalTexture")
if normalBorder then
normalBorder:SetTexture("")
end
-- Hide empty slot background for filled slots
if emptySlotBg then
emptySlotBg:Hide()
end
-- Search filtering (pfUI style - ONLY use alpha, no other effects)
if matchesFilter then
-- Matching items: full opacity (1.0)
self:SetAlpha(1.0)
else
-- Non-matching items: 25% opacity (0.25) - very dim
self:SetAlpha(0.25)
end
-- Set count
if itemData.count and itemData.count > 1 then
countText:SetText(itemData.count)
countText:Show()
else
countText:Hide()
end
-- Set quality border
if itemData.quality and itemData.quality > 1 then
local r, g, b = addon.Modules.Utils:GetQualityColor(itemData.quality)
qualityBorder:SetVertexColor(r, g, b, 1)
qualityBorder:Show()
else
qualityBorder:Hide()
end
self:Show()
else
self.hasItem = false
-- For empty slots, clear the icon texture
SetItemButtonTexture(self, nil)
-- Hide NormalTexture for empty slots (we use EmptySlotBg instead)
self:SetNormalTexture("")
local normalBorder = getglobal(self:GetName().."NormalTexture")
if normalBorder then
normalBorder:SetTexture("")
end
-- Show classic bag pattern background for empty slots
if emptySlotBg then
emptySlotBg:Show()
emptySlotBg:SetAlpha(0.5) -- Slightly more visible
end
-- Dim empty slots when searching (pfUI style)
if matchesFilter then
-- No search active or passes filter: normal opacity
self:SetAlpha(1.0)
else
-- Search active and doesn't match: very dim (25% like pfUI)
self:SetAlpha(0.25)
end
countText:Hide()
qualityBorder:Hide()
self:Show()
end
-- Setup icon texture using pfUI's approach (anchor to fill button)
-- In 1.12.1, ItemButtonTemplate creates an icon named "$parentIconTexture"
local iconTexture = getglobal(self:GetName().."IconTexture")
if not iconTexture then
-- Fallback for other naming conventions
iconTexture = getglobal(self:GetName().."Icon") or self.icon or self.Icon
end
if iconTexture then
if self.hasItem then
-- pfUI style: anchor to fill the button with small insets
iconTexture:ClearAllPoints()
iconTexture:SetPoint("TOPLEFT", self, "TOPLEFT", 1, -1)
iconTexture:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -1, 1)
-- Crop icon edges slightly (pfUI uses .08 to .92)
iconTexture:SetTexCoord(0.08, 0.92, 0.08, 0.92)
iconTexture:Show()
else
-- Hide icon for empty slots
iconTexture:Hide()
end
end
end
-- OnEnter handler (show tooltip)
function Guda_ItemButton_OnEnter(self)
if not self.hasItem or not self.itemData then
return
end
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
if self.otherChar then
-- Viewing another character's item
if self.itemData.link then
GameTooltip:SetHyperlink(self.itemData.link)
GameTooltip:AddLine(" ")
GameTooltip:AddLine("|cFFFFFFFFOwned by: |cFF00FF96" .. self.otherChar .. "|r", 1, 1, 1)
end
else
-- Current character's item
if self.isBank then
GameTooltip:SetInventoryItem("player", BankButtonIDToInvSlotID(self.slotID, self.bagID))
else
GameTooltip:SetBagItem(self.bagID, self.slotID)
end
end
GameTooltip:Show()
end
-- OnLeave handler
function Guda_ItemButton_OnLeave(self)
GameTooltip:Hide()
end
-- OnDragStart handler
function Guda_ItemButton_OnDragStart(self, button)
-- Don't allow dragging other characters' items
if self.otherChar then
return
end
-- Only allow left button drag
if button == "LeftButton" and self.hasItem then
PickupContainerItem(self.bagID, self.slotID)
end
end
-- OnReceiveDrag handler
function Guda_ItemButton_OnReceiveDrag(self)
-- Don't allow dragging to other characters' items
if self.otherChar then
return
end
-- Place the item being dragged
PickupContainerItem(self.bagID, self.slotID)
end
-- OnClick handler
function Guda_ItemButton_OnClick(self, button)
-- Don't allow interaction with other characters' items
if self.otherChar then
return
end
-- Handle modified clicks first
if IsShiftKeyDown() then
-- Shift+Click: Link in chat
if self.hasItem and self.itemData and self.itemData.link then
if ChatFrameEditBox:IsVisible() then
ChatFrameEditBox:Insert(self.itemData.link)
end
end
return
elseif IsControlKeyDown() then
-- Ctrl+Click: Dress up (if applicable)
if self.hasItem and self.itemData and self.itemData.link then
DressUpItemLink(self.itemData.link)
end
return
end
-- Normal clicks - handle item pickup/placement
if button == "LeftButton" then
-- Pick up or place item
PickupContainerItem(self.bagID, self.slotID)
elseif button == "RightButton" then
-- Right click: Use item (only if slot has an item)
if self.hasItem then
UseContainerItem(self.bagID, self.slotID)
end
end
end
-- Release all buttons
function Guda_ReleaseAllButtons()
for _, button in pairs(buttonPool) do
button:Hide()
button:ClearAllPoints()
end
end
+64
View File
@@ -0,0 +1,64 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/">
<!-- Item Button Template -->
<Button name="Guda_ItemButtonTemplate" virtual="true" inherits="ItemButtonTemplate">
<Size>
<AbsDimension x="37" y="37"/>
</Size>
<Layers>
<!-- Empty slot background texture (classic bag pattern) -->
<Layer level="BACKGROUND">
<Texture name="$parent_EmptySlotBg" file="Interface\Buttons\UI-EmptySlot" hidden="false">
<Anchors>
<Anchor point="TOPLEFT"/>
<Anchor point="BOTTOMRIGHT"/>
</Anchors>
</Texture>
</Layer>
<!-- Quality border -->
<Layer level="OVERLAY">
<Texture name="$parent_QualityBorder" hidden="true">
<Anchors>
<Anchor point="TOPLEFT" x="-1" y="1"/>
<Anchor point="BOTTOMRIGHT" x="1" y="-1"/>
</Anchors>
</Texture>
</Layer>
<!-- Item count -->
<Layer level="OVERLAY">
<FontString name="$parent_Count" inherits="NumberFontNormal" justifyH="RIGHT">
<Anchors>
<Anchor point="BOTTOMRIGHT" x="-2" y="2"/>
</Anchors>
</FontString>
</Layer>
</Layers>
<Scripts>
<OnLoad>
Guda_ItemButton_OnLoad(this)
this:RegisterForDrag("LeftButton")
this:RegisterForClicks("LeftButtonUp", "RightButtonUp")
</OnLoad>
<OnEnter>
Guda_ItemButton_OnEnter(this)
</OnEnter>
<OnLeave>
Guda_ItemButton_OnLeave(this)
</OnLeave>
<OnClick>
Guda_ItemButton_OnClick(this, arg1)
</OnClick>
<OnDragStart>
Guda_ItemButton_OnDragStart(this, arg1)
</OnDragStart>
<OnReceiveDrag>
Guda_ItemButton_OnReceiveDrag(this)
</OnReceiveDrag>
</Scripts>
</Button>
</Ui>
+57
View File
@@ -0,0 +1,57 @@
-- Guda Money Display
-- Handles money display in UI
local addon = Guda
local MoneyDisplay = {}
addon.Modules.MoneyDisplay = MoneyDisplay
-- Create a money display frame
function MoneyDisplay:CreateDisplay(parent, x, y)
local frame = CreateFrame("Frame", nil, parent)
frame:SetPoint("TOPLEFT", parent, "TOPLEFT", x, y)
frame:SetWidth(200)
frame:SetHeight(20)
-- Gold text
frame.gold = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
frame.gold:SetPoint("LEFT", frame, "LEFT", 0, 0)
-- Silver text
frame.silver = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
frame.silver:SetPoint("LEFT", frame.gold, "RIGHT", 2, 0)
-- Copper text
frame.copper = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
frame.copper:SetPoint("LEFT", frame.silver, "RIGHT", 2, 0)
return frame
end
-- Update money display
function MoneyDisplay:Update(frame, copper)
if not frame or not copper then
return
end
local gold = math.floor(copper / 10000)
local silver = math.floor(mod(copper, 10000) / 100)
local bronze = mod(copper, 100)
if gold > 0 then
frame.gold:SetText(gold .. "|cFFFFD700g|r")
frame.gold:Show()
else
frame.gold:Hide()
end
if silver > 0 or gold > 0 then
frame.silver:SetText(silver .. "|cFFC0C0C0s|r")
frame.silver:Show()
else
frame.silver:Hide()
end
frame.copper:SetText(bronze .. "|cFFFF6600c|r")
frame.copper:Show()
end
+279
View File
@@ -0,0 +1,279 @@
-- Guda Settings Popup
-- UI for adjusting addon settings
local addon = Guda
local SettingsPopup = {}
addon.Modules.SettingsPopup = SettingsPopup
-- Global function to open settings (called from XML)
function Guda_OpenSettings()
local frame = getglobal("Guda_SettingsPopup")
if frame then
frame:Show()
end
end
-- OnLoad
function Guda_SettingsPopup_OnLoad(self)
local title = getglobal(self:GetName().."_Title")
title:SetText("Guda Settings")
-- Increase title font size
local titleFont, _, titleFlags = title:GetFont()
if titleFont then
title:SetFont(titleFont, 16, titleFlags)
end
Guda:Debug("Settings popup loaded")
end
-- OnShow
function Guda_SettingsPopup_OnShow(self)
-- Load current settings
local bagColumns = Guda.Modules.DB:GetSetting("bagColumns") or 10
local bankColumns = Guda.Modules.DB:GetSetting("bankColumns") or 15
local iconSize = Guda.Modules.DB:GetSetting("iconSize") or addon.Constants.BUTTON_SIZE
local iconFontSize = Guda.Modules.DB:GetSetting("iconFontSize") or 12
local lockBags = Guda.Modules.DB:GetSetting("lockBags")
if lockBags == nil then
lockBags = false
end
-- Update sliders
local bagSlider = getglobal("Guda_SettingsPopup_BagColumnsSlider")
local bankSlider = getglobal("Guda_SettingsPopup_BankColumnsSlider")
local iconSizeSlider = getglobal("Guda_SettingsPopup_IconSizeSlider")
local iconFontSizeSlider = getglobal("Guda_SettingsPopup_IconFontSizeSlider")
local lockCheckbox = getglobal("Guda_SettingsPopup_LockBagsCheckbox")
if bagSlider then
bagSlider:SetValue(bagColumns)
end
if bankSlider then
bankSlider:SetValue(bankColumns)
end
if iconSizeSlider then
iconSizeSlider:SetValue(iconSize)
end
if iconFontSizeSlider then
iconFontSizeSlider:SetValue(iconFontSize)
end
if lockCheckbox then
lockCheckbox:SetChecked(lockBags and 1 or 0)
end
end
-- Toggle visibility
function SettingsPopup:Toggle()
local frame = getglobal("Guda_SettingsPopup")
if frame then
if frame:IsShown() then
frame:Hide()
else
frame:Show()
end
end
end
-- Bag Columns Slider OnLoad
function Guda_SettingsPopup_BagColumnsSlider_OnLoad(self)
getglobal(self:GetName().."Low"):SetText("5")
getglobal(self:GetName().."High"):SetText("20")
local text = getglobal(self:GetName().."Text")
text:SetText("Bag columns")
-- Increase font size
local font, _, flags = text:GetFont()
if font then
text:SetFont(font, 12, flags)
end
self:SetMinMaxValues(5, 20)
self:SetValueStep(1)
local currentValue = Guda.Modules.DB:GetSetting("bagColumns") or 10
self:SetValue(currentValue)
end
-- Bag Columns Slider OnValueChanged
function Guda_SettingsPopup_BagColumnsSlider_OnValueChanged(self)
local value = self:GetValue()
-- Update display text
getglobal(self:GetName().."Text"):SetText("Bag columns: " .. value)
-- Save setting
Guda.Modules.DB:SetSetting("bagColumns", value)
-- Refresh bag frame if it's open
local bagFrame = getglobal("Guda_BagFrame")
if bagFrame and bagFrame:IsShown() then
Guda.Modules.BagFrame:Update()
end
end
-- Bank Columns Slider OnLoad
function Guda_SettingsPopup_BankColumnsSlider_OnLoad(self)
getglobal(self:GetName().."Low"):SetText("5")
getglobal(self:GetName().."High"):SetText("20")
local text = getglobal(self:GetName().."Text")
text:SetText("Bank columns")
-- Increase font size
local font, _, flags = text:GetFont()
if font then
text:SetFont(font, 12, flags)
end
self:SetMinMaxValues(5, 20)
self:SetValueStep(1)
local currentValue = Guda.Modules.DB:GetSetting("bankColumns") or 15
self:SetValue(currentValue)
end
-- Bank Columns Slider OnValueChanged
function Guda_SettingsPopup_BankColumnsSlider_OnValueChanged(self)
local value = self:GetValue()
-- Update display text
getglobal(self:GetName().."Text"):SetText("Bank columns: " .. value)
-- Save setting
Guda.Modules.DB:SetSetting("bankColumns", value)
-- Refresh bank frame if it's open
local bankFrame = getglobal("Guda_BankFrame")
if bankFrame and bankFrame:IsShown() then
Guda.Modules.BankFrame:Update()
end
end
-- Icon Size Slider OnLoad
function Guda_SettingsPopup_IconSizeSlider_OnLoad(self)
getglobal(self:GetName().."Low"):SetText("24px")
getglobal(self:GetName().."High"):SetText("64px")
local text = getglobal(self:GetName().."Text")
text:SetText("Icon size")
-- Increase font size
local font, _, flags = text:GetFont()
if font then
text:SetFont(font, 12, flags)
end
self:SetMinMaxValues(24, 64)
self:SetValueStep(1)
local currentValue = Guda.Modules.DB:GetSetting("iconSize") or addon.Constants.BUTTON_SIZE
self:SetValue(currentValue)
end
-- Icon Size Slider OnValueChanged
function Guda_SettingsPopup_IconSizeSlider_OnValueChanged(self)
local value = math.floor(self:GetValue() + 0.5)
getglobal(self:GetName().."Text"):SetText("Icon size: " .. value .. "px")
Guda.Modules.DB:SetSetting("iconSize", value)
local bagFrame = getglobal("Guda_BagFrame")
if bagFrame and bagFrame:IsShown() then
Guda.Modules.BagFrame:Update()
end
local bankFrame = getglobal("Guda_BankFrame")
if bankFrame and bankFrame:IsShown() then
Guda.Modules.BankFrame:Update()
end
end
-- Icon Font Size Slider OnLoad
function Guda_SettingsPopup_IconFontSizeSlider_OnLoad(self)
getglobal(self:GetName().."Low"):SetText("8px")
getglobal(self:GetName().."High"):SetText("20px")
local text = getglobal(self:GetName().."Text")
text:SetText("Icon font size")
-- Increase font size
local font, _, flags = text:GetFont()
if font then
text:SetFont(font, 12, flags)
end
self:SetMinMaxValues(8, 20)
self:SetValueStep(1)
local currentValue = Guda.Modules.DB:GetSetting("iconFontSize") or 12
self:SetValue(currentValue)
end
-- Icon Font Size Slider OnValueChanged
function Guda_SettingsPopup_IconFontSizeSlider_OnValueChanged(self)
local value = math.floor(self:GetValue() + 0.5)
getglobal(self:GetName().."Text"):SetText("Icon font size: " .. value .. "px")
Guda.Modules.DB:SetSetting("iconFontSize", value)
local bagFrame = getglobal("Guda_BagFrame")
if bagFrame and bagFrame:IsShown() then
Guda.Modules.BagFrame:Update()
end
local bankFrame = getglobal("Guda_BankFrame")
if bankFrame and bankFrame:IsShown() then
Guda.Modules.BankFrame:Update()
end
end
-- Lock Bags Checkbox OnLoad
function Guda_SettingsPopup_LockBagsCheckbox_OnLoad(self)
local text = getglobal(self:GetName().."Text")
if text then
text:SetText("Lock Bags")
-- Increase font size
local font, _, flags = text:GetFont()
if font then
text:SetFont(font, 13, flags)
end
end
local isLocked = false
if Guda and Guda.Modules and Guda.Modules.DB then
isLocked = Guda.Modules.DB:GetSetting("lockBags")
if isLocked == nil then
isLocked = false
end
end
self:SetChecked(isLocked and 1 or 0)
end
-- Lock Bags Checkbox OnClick
function Guda_SettingsPopup_LockBagsCheckbox_OnClick(self)
local isChecked = self:GetChecked() == 1
-- Save setting
if Guda and Guda.Modules and Guda.Modules.DB then
Guda.Modules.DB:SetSetting("lockBags", isChecked)
end
-- Update bag frame draggability
if Guda and Guda.Modules and Guda.Modules.BagFrame and Guda.Modules.BagFrame.UpdateLockState then
Guda.Modules.BagFrame:UpdateLockState()
end
end
-- Initialize
function SettingsPopup:Initialize()
Guda:Debug("Settings popup initialized")
end
+181
View File
@@ -0,0 +1,181 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/">
<!-- Settings Popup Frame -->
<Frame name="Guda_SettingsPopup" toplevel="true" movable="true" enableMouse="true" hidden="true" parent="UIParent" frameStrata="DIALOG">
<Size>
<AbsDimension x="320" y="380"/>
</Size>
<Anchors>
<Anchor point="CENTER" relativePoint="CENTER" relativeTo="UIParent">
<Offset>
<AbsDimension x="0" y="0"/>
</Offset>
</Anchor>
</Anchors>
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\DialogFrame\UI-DialogBox-Border" tile="true">
<BackgroundInsets>
<AbsInset left="11" right="12" top="12" bottom="11"/>
</BackgroundInsets>
<TileSize>
<AbsValue val="16"/>
</TileSize>
<EdgeSize>
<AbsValue val="32"/>
</EdgeSize>
<Color r="0" g="0" b="0" a="0.9"/>
</Backdrop>
<Layers>
<!-- Title -->
<Layer level="ARTWORK">
<FontString name="$parent_Title" inherits="GameFontNormalLarge">
<Anchors>
<Anchor point="TOP" x="0" y="-25"/>
</Anchors>
<Color r="1" g="0.82" b="0"/>
</FontString>
</Layer>
</Layers>
<Frames>
<!-- Close Button -->
<Button name="$parent_CloseButton" inherits="UIPanelCloseButton">
<Anchors>
<Anchor point="TOPRIGHT" x="-5" y="-50"/>
</Anchors>
<Scripts>
<OnClick>
Guda_SettingsPopup:Hide()
</OnClick>
</Scripts>
</Button>
<!-- Bag Columns Slider -->
<Slider name="$parent_BagColumnsSlider" inherits="OptionsSliderTemplate">
<Size>
<AbsDimension x="270" y="17"/>
</Size>
<Anchors>
<Anchor point="TOP">
<Offset>
<AbsDimension x="0" y="-90"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnLoad>
Guda_SettingsPopup_BagColumnsSlider_OnLoad(this)
</OnLoad>
<OnValueChanged>
Guda_SettingsPopup_BagColumnsSlider_OnValueChanged(this)
</OnValueChanged>
</Scripts>
</Slider>
<!-- Bank Columns Slider -->
<Slider name="$parent_BankColumnsSlider" inherits="OptionsSliderTemplate">
<Size>
<AbsDimension x="270" y="17"/>
</Size>
<Anchors>
<Anchor point="TOP" relativePoint="BOTTOM" relativeTo="$parent_BagColumnsSlider">
<Offset>
<AbsDimension x="0" y="-40"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnLoad>
Guda_SettingsPopup_BankColumnsSlider_OnLoad(this)
</OnLoad>
<OnValueChanged>
Guda_SettingsPopup_BankColumnsSlider_OnValueChanged(this)
</OnValueChanged>
</Scripts>
</Slider>
<!-- Icon Size Slider -->
<Slider name="$parent_IconSizeSlider" inherits="OptionsSliderTemplate">
<Size>
<AbsDimension x="270" y="17"/>
</Size>
<Anchors>
<Anchor point="TOP" relativePoint="BOTTOM" relativeTo="$parent_BankColumnsSlider">
<Offset>
<AbsDimension x="0" y="-40"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnLoad>
Guda_SettingsPopup_IconSizeSlider_OnLoad(this)
</OnLoad>
<OnValueChanged>
Guda_SettingsPopup_IconSizeSlider_OnValueChanged(this)
</OnValueChanged>
</Scripts>
</Slider>
<!-- Icon Font Size Slider -->
<Slider name="$parent_IconFontSizeSlider" inherits="OptionsSliderTemplate">
<Size>
<AbsDimension x="270" y="17"/>
</Size>
<Anchors>
<Anchor point="TOP" relativePoint="BOTTOM" relativeTo="$parent_IconSizeSlider">
<Offset>
<AbsDimension x="0" y="-40"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnLoad>
Guda_SettingsPopup_IconFontSizeSlider_OnLoad(this)
</OnLoad>
<OnValueChanged>
Guda_SettingsPopup_IconFontSizeSlider_OnValueChanged(this)
</OnValueChanged>
</Scripts>
</Slider>
<!-- Lock Bags Checkbox -->
<CheckButton name="$parent_LockBagsCheckbox" inherits="OptionsCheckButtonTemplate">
<Anchors>
<Anchor point="TOP" relativePoint="BOTTOM" relativeTo="$parent_IconFontSizeSlider">
<Offset>
<AbsDimension x="-120" y="-30"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnLoad>
Guda_SettingsPopup_LockBagsCheckbox_OnLoad(this)
</OnLoad>
<OnClick>
Guda_SettingsPopup_LockBagsCheckbox_OnClick(this)
</OnClick>
</Scripts>
</CheckButton>
</Frames>
<Scripts>
<OnLoad>
Guda_SettingsPopup_OnLoad(this)
</OnLoad>
<OnShow>
Guda_SettingsPopup_OnShow(this)
</OnShow>
<OnMouseDown>
if (arg1 == "LeftButton") then
this:StartMoving()
end
</OnMouseDown>
<OnMouseUp>
this:StopMovingOrSizing()
</OnMouseUp>
</Scripts>
</Frame>
</Ui>