diff --git a/EllesmereUI.lua b/EllesmereUI.lua index 4fa0f899..5a1acb72 100644 --- a/EllesmereUI.lua +++ b/EllesmereUI.lua @@ -3818,7 +3818,7 @@ local function CreateMainFrame() -- Release cached pages for non-active tabs to free memory. -- Keep the active page so reopening shows the same content. if _pageCache then - local activeKey = activeModule and activePage and (activeModule .. "::" .. activePage) + local activeKey = activeModule and activePage and PageCacheKey(activeModule, activePage) for key, entry in pairs(_pageCache) do if key ~= activeKey then if entry.wrapper then @@ -5801,6 +5801,7 @@ end -- Inline Search (filter sections on the current page) ------------------------------------------------------------------------------- local _pageCache -- forward declaration; initialized below in page-cache section +local PageCacheKey -- forward declaration; assigned with _pageCache init below -- Pool of reusable highlight border frames (accent-colored, fade-in only) local _searchHighlightPool = {} local _searchHighlightsActive = {} @@ -5942,7 +5943,7 @@ function EllesmereUI:NavigateToElementSettings(moduleName, pageName, sectionName end C_Timer.After(0.05, function() - local cacheKey = moduleName .. "::" .. pageName + local cacheKey = PageCacheKey(moduleName, pageName) local cached = _pageCache[cacheKey] if not cached or not cached.wrapper then return end @@ -5996,7 +5997,7 @@ end function EllesmereUI:ApplyInlineSearch(query, skipHighlights) if not activeModule or not activePage then return end - local cacheKey = activeModule .. "::" .. activePage + local cacheKey = PageCacheKey(activeModule, activePage) local cached = _pageCache[cacheKey] if not cached or not cached.wrapper then return end @@ -6400,11 +6401,22 @@ end ------------------------------------------------------------------------------- -- Page / Module Selection ------------------------------------------------------------------------------- --- Page cache: maps "moduleName::pageName" -> { wrapper, totalH, headerBuilder } +-- Page cache: maps "moduleName::pageName" (optional "::vN" from config.pageLayoutVersion) +-- -> { wrapper, totalH, headerBuilder } -- On revisit, we show the cached wrapper and refresh widget values instead of rebuilding. _pageCache = {} local _activePageWrapper -- the currently-visible wrapper frame +PageCacheKey = function(moduleName, pageName) + if not moduleName or not pageName then return nil end + local cfg = modules[moduleName] + local v = cfg and cfg.pageLayoutVersion + if v then + return moduleName .. "::" .. pageName .. "::v" .. tostring(v) + end + return moduleName .. "::" .. pageName +end + -- Invalidate all cached pages (called on profile reset, module reload, etc.) function EllesmereUI:InvalidatePageCache() for key, entry in pairs(_pageCache) do @@ -6449,7 +6461,7 @@ function EllesmereUI:SelectPage(pageName) -- Save current page's refresh list before switching if activePage then - local oldKey = activeModule .. "::" .. activePage + local oldKey = PageCacheKey(activeModule, activePage) if _pageCache[oldKey] then local rl = _pageCache[oldKey].refreshList if not rl then rl = {}; _pageCache[oldKey].refreshList = rl end @@ -6472,7 +6484,7 @@ function EllesmereUI:SelectPage(pageName) tabBar._searchBox:SetText("") end - local cacheKey = activeModule .. "::" .. pageName + local cacheKey = PageCacheKey(activeModule, pageName) local cached = _pageCache[cacheKey] if cached and cached.wrapper then @@ -6705,7 +6717,7 @@ function EllesmereUI:RefreshPage(force) -- when the user switches back to that tab. If they've been orphaned, -- Show() makes them appear detached and the layout breaks ("settings fly -- all over the screen" bug). - local cacheKey = activeModule .. "::" .. activePage + local cacheKey = PageCacheKey(activeModule, activePage) local oldEntry = _pageCache[cacheKey] if oldEntry and oldEntry.wrapper then oldEntry.wrapper:Hide() @@ -6781,7 +6793,7 @@ function EllesmereUI:SelectModule(folderName) -- Save current page's content header under the CORRECT old key -- before we overwrite activeModule. if activePage and activeModule then - local oldKey = activeModule .. "::" .. activePage + local oldKey = PageCacheKey(activeModule, activePage) if _pageCache[oldKey] then local rl = _pageCache[oldKey].refreshList if not rl then rl = {}; _pageCache[oldKey].refreshList = rl end diff --git a/EllesmereUIMinimap/EUI_Minimap_Options.lua b/EllesmereUIMinimap/EUI_Minimap_Options.lua index 2f6b3154..6c0a55b8 100644 --- a/EllesmereUIMinimap/EUI_Minimap_Options.lua +++ b/EllesmereUIMinimap/EUI_Minimap_Options.lua @@ -323,9 +323,18 @@ initFrame:SetScript("OnEvent", function(self) EllesmereUI.RegisterWidgetRefresh(cbDDRefresh) end - -- Interactable Button Size | Outer-Group MM Button Size (toggle + cog) - local customBtnRow - customBtnRow, h = W:DualRow(parent, y, + -- Expand direction | Interactable Button Size + _, h = W:DualRow(parent, y, + { type="dropdown", text="Expand direction", + tooltip="When grouped addon minimap buttons open from the stack toggle, expand toward the minimap (right) or away from it (left).", + values = { right = "Right", left = "Left" }, + order = { "right", "left" }, + getValue=function() local m = MinimapDB(); return (m and m.addonFlyoutExpand) or "right" end, + setValue=function(v) + local m = MinimapDB(); if not m then return end + m.addonFlyoutExpand = v + RefreshMinimap() + end }, { type="slider", text="Interactable Button Size", min=16, max=40, step=1, tooltip="Size of mail, calendar, tracking, and minimap button group toggle", getValue=function() local m = MinimapDB(); return m and m.interactableBtnSize or 21 end, @@ -333,7 +342,12 @@ initFrame:SetScript("OnEvent", function(self) local m = MinimapDB(); if not m then return end m.interactableBtnSize = v RefreshMinimap() - end }, + end } + ); y = y - h + + -- Outer-Group MM Button Size (toggle + cog) | Free Move Buttons + local customBtnRow + customBtnRow, h = W:DualRow(parent, y, { type="toggle", text="Outer-Group MM Button Size", tooltip="Override the size of ungrouped minimap buttons independently from the interactable button size.", getValue=function() local m = MinimapDB(); return m and m.customBtnSizeEnabled end, @@ -342,12 +356,23 @@ initFrame:SetScript("OnEvent", function(self) m.customBtnSizeEnabled = v RefreshMinimap() EllesmereUI:RefreshPage() + end }, + { type="toggle", text="Free Move Buttons", + tooltip="When enabled, Shift+Click any minimap button (mail, calendar, tracking, addon buttons) to drag it to a custom position.", + getValue=function() local m = MinimapDB(); return m and m.freeMoveBtns end, + setValue=function(v) + local m = MinimapDB(); if not m then return end + m.freeMoveBtns = v + if not v then + m.btnPositions = {} + end + RefreshMinimap() end } ); y = y - h -- Inline cog on Outer-Group MM Button Size for size slider do - local rgn = customBtnRow._rightRegion + local rgn = customBtnRow._leftRegion local function isOff() local m = MinimapDB(); return m and (not m.customBtnSizeEnabled) end @@ -386,19 +411,8 @@ initFrame:SetScript("OnEvent", function(self) if isOff() then cogBlock:Show() else cogBlock:Hide() end end - -- Free Move Buttons | Button Backgrounds + -- Button Backgrounds | Hide Great Vault Button _, h = W:DualRow(parent, y, - { type="toggle", text="Free Move Buttons", - tooltip="When enabled, Shift+Click any minimap button (mail, calendar, tracking, addon buttons) to drag it to a custom position.", - getValue=function() local m = MinimapDB(); return m and m.freeMoveBtns end, - setValue=function(v) - local m = MinimapDB(); if not m then return end - m.freeMoveBtns = v - if not v then - m.btnPositions = {} - end - RefreshMinimap() - end }, { type="toggle", text="Button Backgrounds", tooltip="Show black backgrounds behind minimap indicator buttons (tracking, calendar, mail, crafting, addon buttons, flyout toggle).", getValue=function() local m = MinimapDB(); return m and m.btnBackgrounds ~= false end, @@ -406,11 +420,7 @@ initFrame:SetScript("OnEvent", function(self) local m = MinimapDB(); if not m then return end m.btnBackgrounds = v FullRebuildMinimap() - end } - ); y = y - h - - -- Hide Great Vault Button | Great Vault Extra Info - _, h = W:DualRow(parent, y, + end }, { type="toggle", text="Hide Great Vault Button", tooltip="Hides the Great Vault shortcut button from the minimap button stack.", getValue=function() local m = MinimapDB(); return m and m.hideGreatVault end, @@ -418,7 +428,11 @@ initFrame:SetScript("OnEvent", function(self) local m = MinimapDB(); if not m then return end m.hideGreatVault = v RefreshMinimap() - end }, + end } + ); y = y - h + + -- Great Vault Extra Info | Hide M+ Portals Button + _, h = W:DualRow(parent, y, { type="toggle", text="Great Vault Extra Info", tooltip="Shows a compact weekly progress summary in the Great Vault minimap button tooltip.", getValue=function() @@ -429,11 +443,7 @@ initFrame:SetScript("OnEvent", function(self) local m = MinimapDB(); if not m then return end m.greatVaultExtraInfo = v EllesmereUI:RefreshPage() - end } - ); y = y - h - - -- Hide M+ Portals Button - _, h = W:DualRow(parent, y, + end }, { type="toggle", text="Hide M+ Portals Button", tooltip="Hides the M+ Portals shortcut button from the minimap button stack.", getValue=function() local m = MinimapDB(); return m and m.hidePortals end, @@ -441,8 +451,7 @@ initFrame:SetScript("OnEvent", function(self) local m = MinimapDB(); if not m then return end m.hidePortals = v RefreshMinimap() - end }, - { type="label", text="" } + end } ); y = y - h y = y - 10 @@ -652,7 +661,6 @@ initFrame:SetScript("OnEvent", function(self) if locOff() then cogBlock:Show() else cogBlock:Hide() end end - return math.abs(y) end @@ -662,6 +670,9 @@ initFrame:SetScript("OnEvent", function(self) EllesmereUI:RegisterModule("EllesmereUIMinimap", { title = "Minimap", description = "Custom minimap skin and layout.", + -- Bumps page cache key when this options layout changes (see EllesmereUI.PageCacheKey). + pageLayoutVersion = 5, + searchTerms = { "minimap", "flyout", "expand", "addon button", "ungroup", "grouped" }, pages = { "Minimap" }, buildPage = function(pageName, parent, yOffset) if pageName == "Minimap" then return BuildMinimapPage(pageName, parent, yOffset) end @@ -678,6 +689,12 @@ initFrame:SetScript("OnEvent", function(self) SLASH_EMM1 = "/emm" SlashCmdList.EMM = function() if InCombatLockdown and InCombatLockdown() then return end + local prev = EllesmereUI.GetActiveModule and EllesmereUI:GetActiveModule() EllesmereUI:ShowModule("EllesmereUIMinimap") + -- If we were already on this module, ShowModule no-ops SelectModule; force a layout rebuild + -- so updated options Lua (e.g. new rows) appears without hunting stale page cache. + if prev == "EllesmereUIMinimap" and EllesmereUI.RefreshPage then + EllesmereUI:RefreshPage(true) + end end end) diff --git a/EllesmereUIMinimap/EllesmereUIMinimap.lua b/EllesmereUIMinimap/EllesmereUIMinimap.lua index de1455c7..034b0743 100644 --- a/EllesmereUIMinimap/EllesmereUIMinimap.lua +++ b/EllesmereUIMinimap/EllesmereUIMinimap.lua @@ -48,6 +48,8 @@ local defaults = { hideAddonCompartment = false, hideAddonButtons = false, addonBtnSize = 24, + -- "right" = grid opens toward the minimap; "left" = opens the other way + addonFlyoutExpand = "right", interactableBtnSize = 21, ungroupedButtons = {}, freeMoveBtns = false, @@ -402,6 +404,19 @@ end local _flyoutBuilt = false +local function ApplyFlyoutPanelAnchor() + if not flyoutPanel or not flyoutToggle then return end + local mp = EBS.db and EBS.db.profile.minimap + local dir = (mp and mp.addonFlyoutExpand) or "right" + if dir ~= "left" then dir = "right" end + flyoutPanel:ClearAllPoints() + if dir == "left" then + flyoutPanel:SetPoint("BOTTOMRIGHT", flyoutToggle, "BOTTOMLEFT", -2, 0) + else + flyoutPanel:SetPoint("BOTTOMLEFT", flyoutToggle, "BOTTOMRIGHT", 2, 0) + end +end + local function EnsureFlyoutPanel() if not flyoutPanel then flyoutPanel = CreateFrame("Frame", nil, UIParent, "BackdropTemplate") @@ -413,10 +428,10 @@ local function EnsureFlyoutPanel() }) flyoutPanel:SetBackdropColor(0.1, 0.1, 0.1, 0.9) flyoutPanel:SetBackdropBorderColor(0.3, 0.3, 0.3, 1) - flyoutPanel:SetPoint("BOTTOMLEFT", flyoutToggle, "BOTTOMRIGHT", 2, 0) flyoutPanel:SetClampedToScreen(true) flyoutOwnedFrames[flyoutPanel] = true end + ApplyFlyoutPanelAnchor() end -- Build the flyout contents once. Buttons are reparented into the grid @@ -438,6 +453,9 @@ end -- on buttons that may have been hidden by re-initialization. _G._EMIN_RefreshFlyout = function() InvalidateFlyout() + if flyoutPanel and flyoutToggle then + ApplyFlyoutPanelAnchor() + end if flyoutPanel and flyoutPanel:IsShown() then BuildFlyoutContents() end @@ -2523,6 +2541,9 @@ local function ApplyMinimap() InvalidateFlyout() -- Close the flyout if it was open (layout may have changed) HideFlyoutPanel() + if flyoutPanel and flyoutToggle then + ApplyFlyoutPanelAnchor() + end -- Hide Blizzard zone text (we use our own location bar) local zoneBtn = MinimapZoneTextButton diff --git a/EllesmereUI_Widgets.lua b/EllesmereUI_Widgets.lua index bf9cbcd8..065cf4b9 100644 --- a/EllesmereUI_Widgets.lua +++ b/EllesmereUI_Widgets.lua @@ -2992,6 +2992,14 @@ function WidgetFactory:DualRow(parent, yOffset, leftCfg, rightCfg) BuildHalf(leftRegion, leftCfg) BuildHalf(rightRegion, rightCfg) + -- Full-width left half: hide empty rightRegion so it does not stack above controls. + if not rightCfg then + rightRegion:Hide() + rightRegion:EnableMouse(false) + else + rightRegion:Show() + rightRegion:EnableMouse(true) + end -- Slot-level search labels for per-slot highlighting leftRegion._slotLabel = leftCfg and leftCfg.text or ""