Quantcast

- Alts Menu : Sort toon list by name, regardless of server

urnati [04-30-26 - 17:50]
- Alts Menu : Sort toon list by name, regardless of server
- Titan LDB : fix .notes to show in Config > Plugins
- Titan Utils : LDB fix - tooltip could stay over menu
- TItan Comments to be explicit on tooltip priority order
Filename
Titan/TitanHistory.lua
Titan/TitanLDB.lua
Titan/TitanTemplate.lua
Titan/TitanUtils.lua
TitanAlts/TitanAlts.lua
TitanUI/Tools.lua
diff --git a/Titan/TitanHistory.lua b/Titan/TitanHistory.lua
index e63643d..19b5617 100644
--- a/Titan/TitanHistory.lua
+++ b/Titan/TitanHistory.lua
@@ -10,6 +10,26 @@ These are in a seperate file to
 --- Release notes. Keep structure; most recent on 'top'
 local recent_changes = {
    {
+      version = "9.2.3",
+      when = "2026/06/28",
+      topics = {
+         {
+            topic = "Alts",
+            lines = {
+               "Menu : Sort toon list by name, regardless of server.",
+            },
+         },
+         {
+            topic = "Titan",
+            lines = {
+               "LDB : Comments to be explicit on tooltip priority order; fix .notes to show in Config > Plugins.",
+               "Template : Comments to be explicit on tooltip priority order.",
+               "Utils : LDB fix - tooltip could stay over menu.",
+            },
+         },
+      },
+   },
+   {
       version = "9.2.2",
       when = "2026/04/28",
       topics = {
diff --git a/Titan/TitanLDB.lua b/Titan/TitanLDB.lua
index df430fd..9271299 100644
--- a/Titan/TitanLDB.lua
+++ b/Titan/TitanLDB.lua
@@ -126,6 +126,46 @@ LDBToTitan:RegisterEvent("PLAYER_LOGIN")
 local function GenTooltipScripts(frame)
 	local dbg_msg = "LDB-TT "
 	dbg_msg = dbg_msg .. tostring(frame.registry.id)
+
+	--[[ Note on Tooltips:
+	The LDB spec is unclear on priority of method to choose!
+	The methods include
+	-- .tooltip : Implies LDB will handle update and hide of tooltip frame; dislay addon will handle placement and show only
+	-- OnTooltipShow : Display addon sends a blank GameTooltip type frame to be filled;
+	dislay addon will handle placement and show / hide
+	-- OnEnter / OnLeave : Implies LDB is taking full control of tooltip;
+	dislay addon will call when cursor enters / leaves LDB 'button'
+
+
+	2026 Mar :
+	The 'secret' value changes made in Midnight (12.0.0) caused errors in Titan and 3rd part Titan plugins.
+	Titan needed to use its own tooltip based on the same template as GameTooltip.
+	We realized this was the same as the LDB OnTooltipShow method so
+	this routine was rewritten to share tooltip processing with Titan.
+
+	New registry attributes were added to make implicit agreements with plugins and LDB objects.
+	.tooltip ==> .registry.tooltipDisplayFrame
+	.OnTooltipShow ==> .registry.tooltipTemplateFunction
+
+	Another change was always create the OnEnter and OnLeave scripts on the Titan LDB plugin.
+	If the LDB OnEnter or OnLeave script does not exist, Titan calls its own OnEnter / OnLeave.
+	This is how Titan implements using only one tooltip method with priority being
+	1) OnEnter / Leave
+	2) .tooltip
+	3) .OnTooltipShow
+	We believe this meets the intent of the LDB spec and gives developers the flexability they need.
+
+	Example: The data object example in the LDB spec sets OnEnter and OnLeave. OnEnter uses OnTooltipShow.
+	Titan will only call the LDB OnEnter and ignore the OnTooltipShow.
+
+
+	Also always created are OnClick and OnDoubleClick although Titan does not call its respective routines.
+
+	Always creating these scripts may use a few more cycles but removes the need for callbacks and still
+	allows the LDB to update its scripts as needed.
+	Titan will use the updated script for the next On* call.
+	--]]
+
 	-- Technically the spec states only a data source can have .tooltip and .OnTooltipShow
 	-- but the original development allowed them to exist if the LDB dev added them.
 	if frame.ldb_obj.tooltip then
@@ -141,15 +181,6 @@ local function GenTooltipScripts(frame)
 		-- not on LDB
 	end

-	-- 2026 Mar :
-	-- This was rewritten to share tooltip processes with Titan
-	-- by setting a registry attribute for the type of tooltip processing needed.
-	--
-	-- Another change was to always create the On* scripts on the Titan plugin
-	-- then call the LDB routine, if it exists.
-	-- This may use a few more cycle but removes the need for callbacks and still
-	-- allows the LDB to update the scripts. Titan will use them on the next On* call.
-
 	-- OnEnter
 	-- Technically a launcher does not have OnEnter / Onleave but the original developer
 	-- allowed them to exist if the LDB dev added them.
@@ -489,14 +520,9 @@ local function TitanLDBCreateObject(self, name_str, obj)
 	-- if found we use it, if not we assume that the DO "name"
 	-- attribute is the same as the actual
 	-- addon name, which might not always be the case.
-	-- Titan defaults again to "General" if no categoy is found
-	-- via a check in the menu implementation, later on.
 	local addoncategory, addonversion;
 	local tempname = obj.tocname or name;

-	-- This was a sanity check but does not allow for multiple
-	-- LDB to be within an addon yet act as their own addon.
-	--	if IsAddOnLoaded(tempname) then
 	addoncategory = TitanUtils_GetAddOnMetadata(tempname, "X-Category");
 	registry.category = (addoncategory and xcategories[addoncategory])
 		or (obj.category)
@@ -504,9 +530,12 @@ local function TitanLDBCreateObject(self, name_str, obj)
 	addonversion = TitanUtils_GetAddOnMetadata(tempname, "Version")
 		or (obj.version)
 		or ""
-	registry["version"] = addonversion;
-	registry["notes"] = (TitanUtils_GetAddOnMetadata(tempname, "Notes") or "") .. "\n"
-	--	end
+	registry["version"] = addonversion
+
+	local notes_final = (TitanUtils_GetAddOnMetadata(tempname, "Notes") or "")
+		or (obj.notes)
+		or ""
+	registry["notes"] = notes_final .. "\n" .. notes

 	-- Depending on the LDB type set the control and saved Variables appropriately
 	if obj.type == LAUNCHER then
@@ -545,13 +574,7 @@ local function TitanLDBCreateObject(self, name_str, obj)
 	newTitanFrame:SetToplevel(true);
 	newTitanFrame:RegisterForClicks("LeftButtonUp", "RightButtonUp");

-	-- Use the routines given by the DO in this precedence
-	-- tooltip > OnEnter > OnTooltipShow >
-	-- or register a callback in case it is created later. Per the 1.1 LDB spec
-	-- 2026 Mar Major rewrite to move tooltip logic into TitanTemplate.
-	-- The two LDB schemes (tooltip and OnTooltipShow) will be captured in the registry
-	-- which makes the schemes available to Titan plugins.
-	GenTooltipScripts(newTitanFrame)
+	GenTooltipScripts(newTitanFrame) -- See notes in this routine for details

 	local pew = "event"
 	if Titan__InitializedPEW then
diff --git a/Titan/TitanTemplate.lua b/Titan/TitanTemplate.lua
index b889c0e..dded51c 100644
--- a/Titan/TitanTemplate.lua
+++ b/Titan/TitanTemplate.lua
@@ -324,8 +324,15 @@ local function TitanPanelButton_SetTooltip(self)
 			-- Used by Titan auto hide to better determine which bar the 'pin' / icon is on.
 			self.plugin_id = id
 			self.plugin_frame = TitanUtils_ButtonName(id)
+
+			-- Tooltip method order :
+			-- 1) LDB object OnEnter / OnLeave OVERRIDES!!! This routine will not be called.
+			-- 2) tooltipDisplayFrame
+			-- 3) tooltipTemplateFunction
+			-- 4) tooltipCustomFunction
+			-- 5) tooltipTextFunction
 			if (plugin and plugin.tooltipDisplayFrame) then
-				-- 2026 Mar : Added from LDB to take advantage of Titan processing.
+				-- 2026 Mar : Added from LDB .tooltip to take advantage of Titan processing.
 				-- Plugin is expected to handle its frame!
 				-- Titan will position and show only!
 				-- Plugin must handle any timeout and any other features.
@@ -340,6 +347,7 @@ local function TitanPanelButton_SetTooltip(self)
 				plugin.tooltipDisplayFrame:Show() -- now show it
 			elseif (plugin and plugin.tooltipTemplateFunction) then
 				-- 2026 Mar Added to pass a tooltip frame to a plugin as an explicit agreement.
+				-- Combines the Titan tooltip and LDB OnTooltipShow
 				-- This acts as Blizz GameTooltip so plugin can 'add line' etc.

 				-- Hide the Titan Tooltip in case it is open.
@@ -365,7 +373,7 @@ local function TitanPanelButton_SetTooltip(self)
 				-- changing GameTooltip for custom tooltips creates a hybrid mess...

 				-- This should be treated as deprecated as of 2026 Mar.
-				-- It is left so older plugins will work - but they error as of Midnight (12.0.0)
+				-- It is left so older plugins will work - but they can error as of Midnight (12.0.0)
 				-- Use tooltipTemplateFunction instead!
 				local custom_f = GameTooltip
 				SetPanelTooltip(self, id, custom_f);
diff --git a/Titan/TitanUtils.lua b/Titan/TitanUtils.lua
index bab6e71..506c84e 100644
--- a/Titan/TitanUtils.lua
+++ b/Titan/TitanUtils.lua
@@ -1164,13 +1164,15 @@ end
 function TitanUtils_CheckFrameCounting(frame, elapsed)
 	if (frame:IsVisible()) then
 		if (not frame.frameTimer or not frame.isCounting) then
-			return;
+			frame:Hide() -- just in case
 		elseif (frame.frameTimer < 0) then
-			frame:Hide();
-			frame.frameTimer = nil;
-			frame.isCounting = nil;
+			-- hide and clear
+			frame:Hide()
+			frame.frameTimer = nil
+			frame.isCounting = nil
 		else
-			frame.frameTimer = frame.frameTimer - elapsed;
+			-- count down
+			frame.frameTimer = frame.frameTimer - elapsed
 		end
 	end
 end
diff --git a/TitanAlts/TitanAlts.lua b/TitanAlts/TitanAlts.lua
index 7298ae0..5925b99 100755
--- a/TitanAlts/TitanAlts.lua
+++ b/TitanAlts/TitanAlts.lua
@@ -70,10 +70,11 @@ local Alts = {} -- namespace for Alts routines as needed
 ---@field sync_global boolean -- may implement

 -- ******************************** Variables *******************************
-local alts_tt = {}  -- Holds alt data for tooltip display; gen once except for logged in toon
+local alts_tt = {}  -- Holds alt data for tooltip display
 local alts_tt_sort_col = "" -- one sort to rule them all...
 local alts_tt_sort_ascend = true -- default on click; click again to flip
 local tt_frame = {} -- tooltip on the QTip :)
+local menu_toons = {} -- sorted foir menu

 Titan_Debug.alts = {}
 Titan_Debug.alts.tool_tips = false
@@ -913,23 +914,17 @@ local function GeneratorFunction(owner, rootDescription)
 	--		for idx, pdata in TitanUtils_PlayerIter() do
 	local opts_show_toons = Titan_Menu.AddButton(root, L["TITAN_PANEL_MENU_PROFILE_CHARS"])
 	do -- next level options
-		for idx, pdata in TitanUtils_PlayerIter() do
-			local result, toon_info = TitanUtils_GetProfileInfo(idx, "Alts", false)
-			if result == "is_custom" then
-				-- skip, can not log in
-			elseif toon_info then
-				Titan_Menu.AddSelectorGeneric(opts_show_toons, idx,
-					function(data)
-						return data.toon.show
-					end,
-					function(data)
-						data.toon.show = not data.toon.show
-					end,
-					{ toon = toon_info }
-				)
-			else
-				-- not user selectable to hide
-			end
+		for idx = 1, #menu_toons do -- already curated
+			local result, toon_info = TitanUtils_GetProfileInfo(menu_toons[idx], "Alts", false)
+			Titan_Menu.AddSelectorGeneric(opts_show_toons, menu_toons[idx],
+				function(data)
+					return data.toon.show
+				end,
+				function(data)
+					data.toon.show = not data.toon.show
+				end,
+				{ toon = toon_info }
+			)
 		end
 	end
 	Titan_Menu.SetScroll(opts_show_toons, scroll_hgt) -- in case menu height is larger than screen / window
@@ -1029,6 +1024,27 @@ local function OnShow(self)
 	max_level = GetMaxPlayerLevel() -- GetMaxLevelForPlayerExpansion()

 	TitanPanelGetVar("TooltipTimeout")
+
+	do -- sort toon list for menu; only need once
+		menu_toons = {}
+		for idx, pdata in TitanUtils_PlayerIter() do
+			local result, toon_info = TitanUtils_GetProfileInfo(idx, "Alts", false)
+			if result == "is_custom" then
+				-- skip, can not log in
+			elseif toon_info then
+				table.insert(menu_toons, idx)
+			else
+				-- not user selectable so hide
+			end
+		end
+		-- sort the list, regardless of server
+		for idx = 1, #menu_toons do
+			table.sort(menu_toons, function(a, b)
+				return a < b
+			end)
+		end
+	end
+
 end

 local function OnHide(self)
diff --git a/TitanUI/Tools.lua b/TitanUI/Tools.lua
index ffc6e7c..8788acf 100755
--- a/TitanUI/Tools.lua
+++ b/TitanUI/Tools.lua
@@ -1,227 +1,308 @@
 ---@diagnostic disable: duplicate-set-field
---[[
--- **************************************************************************
--- * TitanUI.lua
--- *
--- * By: The Titan Panel Development Team
--- **************************************************************************
+--[[ TitanUI.lua
+
+The intent of this addon is provide a LDB example that works with Titan.
+See dev notes at bottom.
+
+By: The Titan Panel Development Team
+
 --]]
+
 -- ******************************** Constants *******************************
-local add_on = ...
-local _G = _G --getfenv(0);
-local L = LibStub("AceLocale-3.0"):GetLocale(TITAN_ID, true)
-local AceConfigDialog = LibStub("AceConfigDialog-3.0")

-local artwork_path = "Interface\\AddOns\\TitanUI\\Artwork\\"
-local TITAN_PLUGIN = "TitanUI"
+local add_on_id, name_space = ...                            -- folder and Lua table
+local _G = _G                                                --getfenv(0);
+
+local L = LibStub("AceLocale-3.0"):GetLocale(TITAN_ID, true) -- Titan_ID
+local AceConfigDialog = LibStub("AceConfigDialog-3.0")       -- Titan_ID
+
+local artwork_path = "Interface\\AddOns\\" .. add_on_id .. "\\Artwork\\"
 local TITLE = "Titan UI"
-local TITAN_BUTTON = "TitanPanel" .. TITAN_PLUGIN .. "Button"
-local VERSION = C_AddOns.GetAddOnMetadata(add_on, "Version")
+local add_on_frame_name = "AddonFrame" .. add_on_id .. ""
+local add_on_frame = {}
+local VERSION = C_AddOns.GetAddOnMetadata(add_on_id, "Version")

 -- ******************************** Variables *******************************
 local trace = false -- true / false    Make true when debug output is needed.

---[[
-local function SendSlash(slash, params)
-	DEFAULT_CHAT_FRAME.editBox:SetText(_G[slash] .. " " .. tostring(params))
-	ChatEdit_SendText(DEFAULT_CHAT_FRAME.editBox, 0)
-end
-SendSlash("SLASH_TitanPanel1", "reset")
---]]
 local function SendSlash(slash)
 	DEFAULT_CHAT_FRAME.editBox:SetText(slash)
 	ChatEdit_SendText(DEFAULT_CHAT_FRAME.editBox, 0)
 end

+local function GenCommand(owner, id, label, function_name, ...)
+	--    local callback = function_name
+	local params = ...
+
+	local elementDescription =
+		owner:CreateButton(label, -- was info.text
+			function()      -- was info.func
+				function_name(params)
+			end,
+			id
+		)
+	-- in case we can and want to modify in future...
+	return elementDescription
+end
+
+---comment
+---@param owner any Not used in this routine
+---@param rootDescription table Root Menu object
 local function GeneratorFunction(owner, rootDescription)
-	local id = TITAN_PLUGIN
+	local id = add_on_id
 	local root = rootDescription -- menu widget to start with
+	local elementDescription = {} -- used if creating nested menus

-	local config = L["TITAN_PANEL_MENU_CONFIGURATION"].." "
-	Titan_Menu.AddCommand(root, id, config..L["TITAN_PANEL_MENU_OPTIONS_BARS"],
-		function()
-			TitanUpdateConfig("init")
-			AceConfigDialog:Open("Titan Panel Bars")
-		end)
+	if TitanUpdateConfig then -- Titan_ID
+		local config = L["TITAN_PANEL_MENU_CONFIGURATION"] .. " "
+		GenCommand(root, id, config .. L["TITAN_PANEL_MENU_OPTIONS_BARS"],
+			function()
+				TitanUpdateConfig("init")
+				AceConfigDialog:Open("Titan Panel Bars")
+			end)

-	Titan_Menu.AddCommand(root, id, config..L["TITAN_PANEL_MENU_PLUGINS"],
-		function()
-			TitanUpdateConfig("init")
-			AceConfigDialog:Open("Titan Panel Addon Control")
-		end)
+		GenCommand(root, id, config .. L["TITAN_PANEL_MENU_PLUGINS"],
+			function()
+				TitanUpdateConfig("init")
+				AceConfigDialog:Open("Titan Panel Addon Control")
+			end)

-	Titan_Menu.AddCommand(root, id, config..L["TITAN_PANEL_MENU_PROFILES"],
-		function()
-			TitanUpdateConfig("init")
-			AceConfigDialog:Open("Titan Panel Addon Chars")
-		end)
+		GenCommand(root, id, config .. L["TITAN_PANEL_MENU_PROFILES"],
+			function()
+				TitanUpdateConfig("init")
+				AceConfigDialog:Open("Titan Panel Addon Chars")
+			end)

-	Titan_Menu.AddDivider(root)
-	local t_reset = "/titanpanel reset"
-	Titan_Menu.AddCommand(root, id, t_reset,
-		function()
-			SendSlash(t_reset)
-		end)
+		elementDescription = root:CreateDivider()
+		local t_reset = "/titanpanel reset"
+		GenCommand(root, id, t_reset,
+			function()
+				SendSlash(t_reset)
+			end)
+	else
+		-- skip, Titan not enabled
+	end

-	Titan_Menu.AddDivider(root)
+	-- Helpful commands to developers
+	elementDescription = root:CreateDivider()
 	local fstack = "/fstack"
-	Titan_Menu.AddCommand(root, id, fstack,
+	GenCommand(root, id, fstack,
 		function()
 			SendSlash(fstack)
 		end)

-	Titan_Menu.AddDivider(root)
+	elementDescription = root:CreateDivider()
 	local lua_cmd = "/lua"
-	Titan_Menu.AddCommand(root, id, lua_cmd,
+	GenCommand(root, id, lua_cmd,
 		function()
 			SendSlash(lua_cmd)
 		end)

-	Titan_Menu.AddDivider(root)
+	elementDescription = root:CreateDivider()
 	local etrace_cmd = "/eventtrace"
-	Titan_Menu.AddCommand(root, id, etrace_cmd,
+	GenCommand(root, id, etrace_cmd,
 		function()
 			SendSlash(etrace_cmd)
 		end)

-	Titan_Menu.AddDivider(root)
+	elementDescription = root:CreateDivider()
 	local api_cmd = "/api"
-	Titan_Menu.AddCommand(root, id, api_cmd,
+	GenCommand(root, id, api_cmd,
 		function()
 			SendSlash(api_cmd)
 		end)
 end

--- PLAYER_EQUIPMENT_CHANGED
--- Grab the button text to display
-local function GetButtonText(id)
-	local avgItemLevel, avgItemLevelEquipped, avgItemLevelPvp = GetAverageItemLevel()
-	local strA, strB = L["TITAN_PANEL_MENU_RELOADUI"], ""
-	return strA, strB
-end
-
--- Create the tooltip string
-local function GetTooltipText()
+--- Fill the tooltip given by the display addon
+---@param tooltip table Tooltip frame from display addon
+local function GetTooltipText(tooltip)
 	local res = ""
 	local rtn = "\n"
 	local tab = "\t"

-	local realm = TitanUtils_GetNormalText("Current Server :") .. tab
-		.. TitanUtils_GetHighlightText(GetRealmName()) .. rtn
+	tooltip:AddLine(TITLE .. " " .. VERSION)
+
+	tooltip:AddDoubleLine(TitanUtils_GetNormalText("Current Server :"),
+		TitanUtils_GetHighlightText(GetRealmName()))
+
+	tooltip:AddLine("  ")

 	local now = _G.time()

 	local resets = "Resets in Server Time" .. rtn
+	tooltip:AddLine(resets)
 	local week_reset = C_DateAndTime.GetSecondsUntilWeeklyReset()
-	local weekly = TitanUtils_GetNormalText("Weekly :") .. tab
-		.. TitanUtils_GetHighlightText(TitanUtils_GetDateText(week_reset + now, true)) .. rtn
+	tooltip:AddDoubleLine(TitanUtils_GetNormalText("Weekly :"),
+		TitanUtils_GetHighlightText(TitanUtils_GetDateText(week_reset + now, true)))

 	local day_reset = C_DateAndTime.GetSecondsUntilDailyReset()
-	local daily = TitanUtils_GetNormalText("Daily :") .. tab
-		.. TitanUtils_GetHighlightText(TitanUtils_GetDateText(day_reset + now, true)) .. rtn
+	tooltip:AddDoubleLine(TitanUtils_GetNormalText("Daily :"),
+		TitanUtils_GetHighlightText(TitanUtils_GetDateText(day_reset + now, true)))
+
+	tooltip:AddLine("  ")
+
+	tooltip:AddLine(TitanUtils_GetGreenText("Left Click: Reloads the User Interface"))
+	tooltip:AddLine(TitanUtils_GetGreenText("Right Click: For Shortcuts and Debug Tools"))
+end

-	local hints = ""
-		.. TitanUtils_GetGreenText("Left Click: Reloads the User Interface") .. rtn
-		.. TitanUtils_GetGreenText("Right Click: For Shortcuts and Debug Tools") .. rtn
+---Create a header with the text and color given
+---@param owner table Menu object
+---@param label string Text to use
+---@param color table Color to use
+---@return table menu_obj
+local function GenHeader(owner, label, color)
+	if color == nil then
+		color = GRAY_FONT_COLOR
+	end
+	local elementDescription =
+		owner:CreateTitle(label, color)

-	res = res
-		.. realm
-		.. rtn
-		.. resets .. daily .. weekly
-		.. rtn
-		.. hints
+	elementDescription:AddInitializer(function(frame, description, menu)
+		local fontFile, height, flags = frame.fontString:GetFont()
+	end
+	)

-	return res
+	-- in case we can and want need to modify in future...
+	return elementDescription
 end

--- Create the .registry for Titan so it can register and place the plugin
--- Icon from : https://www.wowhead.com/icon=236372/achievement-bg-returnxflags-def-wsg
+---Create menu to show to user
+---@param owner table Menu object
+---@return table menu_obj
+function AddContextMenu(owner)
+	local function gen_menu(plugin_frame, rootDescription)
+		local root = rootDescription
+		local elementDescription = {}
+
+		elementDescription = root:CreateTitle(TITLE)
+		elementDescription = root:CreateDivider()
+
+		-- Attach widgets or show error!
+		local succ, val = pcall(GeneratorFunction, plugin_frame, root)
+		if succ then
+			-- all good
+		else
+			GenHeader(root, add_on_id .. " !! " .. val, RED_FONT_COLOR)
+		end

+		-- Add the control variables + right side + Hide
+		--			GenControlVars(root, plugin_frame.registry.id, true)
+	end
+
+	-- This does return a menu object but we choose to let Blizz handle opening through closing.
+	return MenuUtil.CreateContextMenu(owner, gen_menu)
+
+	-- CreateContextMenu will take other parameters (as ...) which are passed to GeneratorFunction.
+end
+
+---Create the LDB object and any init
+---@param self table Plugin frame
 local function OnLoad(self)
 	local notes = ""
 		.. "Adds a click to Reload UI and as menu for select help & tools to Titan Panel.\n"
 	--		.."- xxx.\n"
-	self.registry = {
-		id = TITAN_PLUGIN,
-		category = "Built-ins",
-		version = VERSION,
-		menuText = TITLE,
-		--		menuTextFunction = CreateMenu,
-		menuContextFunction = GeneratorFunction, -- NEW scheme
-		buttonTextFunction = GetButtonText,
-		tooltipTitle = TITLE,
-		tooltipTextFunction = GetTooltipText,
-		icon = artwork_path .. "TitanReload",
-		iconWidth = 16,
-		notes = notes,
-		controlVariables = {
-			ShowIcon = true,
-			ShowLabelText = true,
-			--			ShowColoredText = true,
-			DisplayOnRightSide = true,
-		},
-		savedVariables = {
-			ShowIcon = 1,
-			ShowLabelText = 1,
-			--			ShowColoredText = 1,
-			DisplayOnRightSide = false,
-		}
-	};
-end
+	--[[
+	Initialize the Data Broker 'button'.
+	This is the heart of a LDB plugin. It determines how the display addon is to treat this addon.

--- Parse and react to registered events
-local function OnEvent(self, event, a1, a2, ...)
-end
+	On successful :NewDataObject the display addon will have created a 'button' to display.

--- Handle mouse clicks
-local function OnClick(self, button)
-	if trace then
-		TitanPluginDebug(TITAN_PLUGIN, "TUI click"
-			.. " " .. tostring(button) .. ""
-		)
-	end
-	if (button == "LeftButton") then
-		C_UI.Reload() --ReloadUI()
-	end
-end
+	Setting the type is required so the LDB lib and display addon know what to do. See the LDB spec.
+
+	id passed in (add_on_id) will be the name Titan uses for the plugin. Found in the Titan Config or Titan right click menu.
+
+	Below is a simple launcher.
+	If creating a data source then routines will be needed to update .icon; .label; .text as needed.
+	The LDB lib will handle the callback to the display addon.
+
+
+	This addon tells the display addon to give it a blank tooltip by creating OnTooltipShow.
+	When the display addon needs the tooltip, it will call this routine to have it filled in.
+	Then the display addon will handle placement and show / hide.
+
+
+	Note on Tooltips: The LDB spec is unclear on priority of method to choose. These include
+	-- .tooltip : Implies a static tooltip; dislay addon will handle placement and show / hide
+	-- OnTooltipShow : Display addon sends a blank GameTooltip type frame to be filled;
+	dislay addon will handle placement and show / hide
+	-- OnEnter / OnLeave : Implies LDB is taking full control of tooltip;
+	dislay addon will call when cursor enters / leaves LDB 'button'

-local function OnShow(self)
-	TitanPanelButton_UpdateButton(TITAN_PLUGIN);
+
+	--]]
+
+	add_on_frame.obj =
+		LibStub("LibDataBroker-1.1"):NewDataObject(add_on_id, -- Name used within Titan
+			{
+				type          = "launcher",             -- required
+				-- LDB spec: The two options are:
+				--      "data source" - Expected to show some type of info
+				--      "launcher" - Expected to open another window or perform some action
+				icon          = artwork_path .. "TitanReload", -- The icon used by the display addon
+				label         = TITLE,             -- button label used by the display addon
+				text          = "Reload UI", -- info displaed by the display addon; Updated as needed with this plugin if data source
+				OnTooltipShow = function(tooltip)
+					-- For the 'button' the display addon creates
+					-- The display addon will give the empty tooltip then handle placement and show / hide
+					GetTooltipText(tooltip)
+				end,
+				OnClick       = function(self, button)
+					-- For the 'button' the display addon creates
+					if (button == "LeftButton") then
+						C_UI.Reload() -- user wants to reload the WoW UI
+					elseif (button == "RightButton") then
+						-- Create a menu using MenuUtil
+						AddContextMenu(add_on_frame)
+					end
+				end,
+				-- Titan specific!!
+				-- Built-ins is reserved keyword for plugins bundled with Titan; default is General
+				-- TITAN_PANEL_BUTTONS_PLUGIN_CATEGORY has list of categories
+				category      = "Built-ins",
+				notes      = notes,
+			}
+		)
 end

--- ====== Create needed frames
+---Create needed frames
 local function Create_Frames()
-	if _G[TITAN_BUTTON] then
+	if _G[add_on_frame] then
 		return -- if already created
 	end

 	if trace then
-		TitanPluginDebug(TITAN_PLUGIN, "TS frames"
-			.. " '" .. tostring(TITAN_BUTTON) .. "'"
+		TitanPluginDebug(add_on_id, "TS frames"
+			.. " '" .. tostring(add_on_frame_name) .. "'"
 		)
 	end

-	-- general container frame
-	local f = CreateFrame("Frame", nil, UIParent)
-	local window = CreateFrame("Button", TITAN_BUTTON, f, "TitanPanelComboTemplate")
-	window:SetFrameStrata("FULLSCREEN")
+	-- addon frame to get events and scripts
+	add_on_frame = CreateFrame("Button", add_on_frame_name, UIParent)
+	add_on_frame:SetFrameStrata("FULLSCREEN")
 	-- Using SetScript to set "OnLoad" does not work
 	--
-	-- This routine sets the guts of the plugin - the .registry
-	OnLoad(window);
+	-- This routine sets the guts of the LDB addon
+	OnLoad(add_on_frame);

-	window:SetScript("OnShow", function(self)
+	-- There is no frame for the user so On* scripts are not needed.
+	-- The display addon will handle place and react to the LDB object.
+	--[[
+	add_on_frame:SetScript("OnShow", function(self)
 		OnShow(self)
-		-- This routine ensures the plugin is put where the user requested it.
-		-- Titan saves the bar the plugin was on. It does not save the relative order.
-		TitanPanelButton_OnShow(self);
 	end)
-	window:SetScript("OnClick", function(self, button)
+	add_on_frame:SetScript("OnClick", function(self, button)
 		-- Typically this routine handles actions on left click
 		OnClick(self, button);
-		-- Typically this routine handles the menu creation on right click
-		TitanPanelButton_OnClick(self, button);
 	end)
+--]]
 end

 Create_Frames() -- do the work
+
+--[[ Development notes
+The intent of this plugin a LDB example developers can use.
+It also helps ensure Titan changes do not break simple LDB addons :).
+
+This has Titan as a dependency.
+If used as a generic LDB addon then remove all code with TITAN_ID in comments!!!
+--]]