view Modules/Widgets.lua @ 122:6724bc8eface

Reduced usage of global functions by defining them locally.
author Zerotorescue
date Sat, 15 Jan 2011 18:52:01 +0100
parents 3bec0ea44607
children
line wrap: on
line source
local addon = select(2, ...);
local Widgets = addon:NewModule("Widgets");

local AceGUI = LibStub("AceGUI-3.0");

function Widgets:ItemLinkButton()
	--[[
	[ ItemLinkButton ]
	This custom widget has to show an icon with the item link next to it.
	Upon hover it must show the item tooltip.
	Upon click it must execute the function provided through user data.
	
	UserData: itemId, onClickEvent
	
	OnEnter: tooltip show
	OnLeave: tooltip hide
	OnClick: UserData.onClickEvent
	]]
	
	local widgetType = "ItemLinkButton";
	local widgetVersion = 1;
	
	local function Constructor()
	    local widget = AceGUI:Create("InteractiveLabel");
	    widget.type = widgetType;
	    
	    -- We overwrite the OnAcquire as we want to set our callbacks even
	    -- when the widget is re-used from the widget pool
	    widget.originalOnAcquire = widget.OnAcquire;
	    widget.OnAcquire = function(self, ...)
		    
		    
	    	-- We overwrite the setcallback because we don't want anything else 
	    	-- to overwrite our OnEnter, OnLeave and OnClick events
	    	-- which would be done by the AceConfigDialog after a widget gets re-used
		    if not self.originalSetCallBack then
			    self.originalSetCallBack = self.SetCallback;
			    self.SetCallback = function(this, event, func, ...)
			    	if event == "OnEnter" or event == "OnLeave" or event == "OnClick" then
			    		-- Don't allow overwriting of these events
			    		return;
			    	elseif event == "CustomOnEnter" then
			    		return this.originalSetCallBack(this, "OnEnter", func, ...);
			    	elseif event == "CustomOnLeave" then
			    		return this.originalSetCallBack(this, "OnLeave", func, ...);
			    	elseif event == "CustomOnClick" then
			    		return this.originalSetCallBack(this, "OnClick", func, ...);
			    	else
			    		return this.originalSetCallBack(this, event, func, ...);
			    	end
			    end;
		    end
		    
		    
		    
		    -- Set our own events, since we disabled the normal event-names, we'll call them our custom versions
		    self:SetCallback("CustomOnEnter", function(this)
		    	local itemData = this:GetUserData("ItemData");
		    	
		    	if itemData then
			    	GameTooltip:SetOwner(this.frame, "ANCHOR_TOPRIGHT");
			    	GameTooltip:SetHyperlink(("item:%d"):format(itemData.id));
					GameTooltip:Show();
		    	end
		    end);
		    self:SetCallback("CustomOnLeave", function(this)
		    	GameTooltip:Hide();
		    end);
		    self:SetCallback("CustomOnClick", function(this, ...)
		    	-- Below is used in child widgets to prepare for onclick
		    	if this.OnClick then
		    		this.OnClick(this, ...);
		    	end
		    	
		    	local func = this:GetUserData("exec");
		    	local itemData = this:GetUserData("ItemData");
		    	
		    	if func then
		    		-- If this is a config option we will need the group id
		    		local path = this:GetUserData("path");
		    		local groupId = (path and path[2]) or nil;
		    		
		    		func(groupId, itemData, ...);
		    	end
		    end);
		    
		    
		    
		    -- Then also do whatever it wanted to do
		    self.originalOnAcquire(self, ...);
	    end;
	    
	    -- Remember the original SetText as this might get overwritten by the config-widget
	    widget.originalSetText = widget.SetText;
	    
	    widget.SetItem = function(self, item)
 		   	self:SetUserData("ItemData", item);
 		   	
	   		-- Put the icon in front of it
			self:SetImage(item.icon);
			-- Standardize the size
			self:SetImageSize(16, 16);
    		
			-- Make readable font
    		self:SetFontObject(GameFontHighlight);
    		
    		if not item.link then
    			-- If no item link was cached, give it another try
    			
				local itemName, itemLink, itemRarity = GetItemInfo(item.id);
    			
				-- item is a table, so passed by reference, so updatable
				item.name = itemName;
				item.link = itemLink;
				item.rarity = itemRarity;
    		end
    		
    		-- We don't want to set the itemId as text, but rather the item link, so get that.
    		local itemLink = item.link or ("Unknown (#%d)"):format(item.id);
    		
    		self:originalSetText(itemLink);
	    end;
		
		return widget;
	end
    
	AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion);
end

function Widgets:ConfigItemLinkButton()
	-- Define out custom item link button widget
	-- This will be called as if it's an input element, we overwrite some of the related functions which are called for default input fields
	
	local widgetType = "ConfigItemLinkButton";
	local widgetVersion = 1;
	
	-- Empty function for disabling functions
	local function Dummy() end
	
	-- Makes an instance of our ItemLinkButton widget
	local function GetItemLinkButton()
	    local widget = AceGUI:Create("ItemLinkButton");
	    widget.type = widgetType;
	    
	    -- We can only provide custom widgets for input, select and multiselect fields
	    -- Input being the simplest, we use that - however, it provides two parameters: label and text. We only need one, disable the other.
	    widget.SetLabel = Dummy;
	    
	    -- SetText is called when this button is being created and contains the itemId
	    -- Forward that itemId to the ItemLinkButton
	    widget.SetText = function(self, value, ...)
	    	if value and tonumber(value) then
				local newItemData = addon.ItemData:New(tonumber(value));
		    	
	 		   	self:SetItem(newItemData);
	    	end
		end;
		
		widget.OnClick = function(self, ...)
			local option = self:GetUserData("option");
	    	
	    	if option and option.set then
				self:SetUserData("exec", option.set);
			end
		end;
	    
	    return widget;
	end
    
	AceGUI:RegisterWidgetType(widgetType, GetItemLinkButton, widgetVersion);
end

function Widgets:InlineGroupWithButton()
	-- Register InlineGroupWithButton-widget
	-- This widget adds a button next to the header of an inline group
	-- SetPoint doesn't seem usable within AceGUI.
	
	local widgetType = "InlineGroupWithButton";
	local widgetVersion = 1;

	local function Constructor() 
	    local widget = AceGUI:Create("InlineGroup");
	    widget.type = widgetType;
	    
	    widget.MakeButton = function(self, buttonSettings)
			if type(buttonSettings) == "table" then
				if not self.btnQueue then
					-- Because widgets are re-used, we don't want to recreate this button
					self.btnQueue = CreateFrame("Button", nil, self.frame, "UIPanelButtonTemplate");
					self.btnQueue:SetHeight(22);
					self.btnQueue:SetWidth(120);
				end
				self.btnQueue:SetText(buttonSettings.name);
				self.btnQueue:SetPoint("TOPRIGHT", self.frame, "TOPRIGHT", -10, 5);
				
				-- Triggers
				self.btnQueue:SetScript("OnClick", buttonSettings.exec);
				
				-- Tooltip
				self.btnQueue.tooltipTitle = buttonSettings.name;
				self.btnQueue.tooltip = buttonSettings.desc or "";
				self.btnQueue:SetScript("OnEnter", ShowTooltip);
				self.btnQueue:SetScript("OnLeave", HideTooltip);
			else
				error("settings must be a table - usage: MakeButton(table);");
			end
	    end;
		
	    return widget;
	end
    
	AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion);
end