| Asa@0 | 1 --[[ $Id: AceGUIWidget-DropDown.lua 877 2009-11-02 15:56:50Z nevcairiel $ ]]-- | 
| Asa@0 | 2 local AceGUI = LibStub("AceGUI-3.0") | 
| Asa@0 | 3 | 
| Asa@0 | 4 -- Lua APIs | 
| Asa@0 | 5 local min, max, floor = math.min, math.max, math.floor | 
| Asa@0 | 6 local select, pairs, ipairs = select, pairs, ipairs | 
| Asa@0 | 7 local tsort = table.sort | 
| Asa@0 | 8 | 
| Asa@0 | 9 -- WoW APIs | 
| Asa@0 | 10 local UIParent, CreateFrame = UIParent, CreateFrame | 
| Asa@0 | 11 local _G = _G | 
| Asa@0 | 12 | 
| Asa@0 | 13 -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded | 
| Asa@0 | 14 -- List them here for Mikk's FindGlobals script | 
| Asa@0 | 15 -- GLOBALS: CLOSE | 
| Asa@0 | 16 | 
| Asa@0 | 17 local function fixlevels(parent,...) | 
| Asa@0 | 18 	local i = 1 | 
| Asa@0 | 19 	local child = select(i, ...) | 
| Asa@0 | 20 	while child do | 
| Asa@0 | 21 		child:SetFrameLevel(parent:GetFrameLevel()+1) | 
| Asa@0 | 22 		fixlevels(child, child:GetChildren()) | 
| Asa@0 | 23 		i = i + 1 | 
| Asa@0 | 24 		child = select(i, ...) | 
| Asa@0 | 25 	end | 
| Asa@0 | 26 end | 
| Asa@0 | 27 | 
| Asa@0 | 28 local function fixstrata(strata, parent, ...) | 
| Asa@0 | 29 	local i = 1 | 
| Asa@0 | 30 	local child = select(i, ...) | 
| Asa@0 | 31 	parent:SetFrameStrata(strata) | 
| Asa@0 | 32 	while child do | 
| Asa@0 | 33 		fixstrata(strata, child, child:GetChildren()) | 
| Asa@0 | 34 		i = i + 1 | 
| Asa@0 | 35 		child = select(i, ...) | 
| Asa@0 | 36 	end | 
| Asa@0 | 37 end | 
| Asa@0 | 38 | 
| Asa@0 | 39 do | 
| Asa@0 | 40 	local widgetType = "Dropdown-Pullout" | 
| Asa@0 | 41 	local widgetVersion = 3 | 
| Asa@0 | 42 | 
| Asa@0 | 43 	--[[ Static data ]]-- | 
| Asa@0 | 44 | 
| Asa@0 | 45 	local backdrop = { | 
| Asa@0 | 46 		bgFile = "Interface\\ChatFrame\\ChatFrameBackground", | 
| Asa@0 | 47 		edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", | 
| Asa@0 | 48 		edgeSize = 32, | 
| Asa@0 | 49 		tileSize = 32, | 
| Asa@0 | 50 		tile = true, | 
| Asa@0 | 51 		insets = { left = 11, right = 12, top = 12, bottom = 11 }, | 
| Asa@0 | 52 	} | 
| Asa@0 | 53 	local sliderBackdrop  = { | 
| Asa@0 | 54 		bgFile = "Interface\\Buttons\\UI-SliderBar-Background", | 
| Asa@0 | 55 		edgeFile = "Interface\\Buttons\\UI-SliderBar-Border", | 
| Asa@0 | 56 		tile = true, tileSize = 8, edgeSize = 8, | 
| Asa@0 | 57 		insets = { left = 3, right = 3, top = 3, bottom = 3 } | 
| Asa@0 | 58 	} | 
| Asa@0 | 59 | 
| Asa@0 | 60 	local defaultWidth = 200 | 
| Asa@0 | 61 	local defaultMaxHeight = 600 | 
| Asa@0 | 62 | 
| Asa@0 | 63 	--[[ UI Event Handlers ]]-- | 
| Asa@0 | 64 | 
| Asa@0 | 65 	-- HACK: This should be no part of the pullout, but there | 
| Asa@0 | 66 	--       is no other 'clean' way to response to any item-OnEnter | 
| Asa@0 | 67 	--       Used to close Submenus when an other item is entered | 
| Asa@0 | 68 	local function OnEnter(item) | 
| Asa@0 | 69 		local self = item.pullout | 
| Asa@0 | 70 		for k, v in ipairs(self.items) do | 
| Asa@0 | 71 			if v.CloseMenu and v ~= item then | 
| Asa@0 | 72 				v:CloseMenu() | 
| Asa@0 | 73 			end | 
| Asa@0 | 74 		end | 
| Asa@0 | 75 	end | 
| Asa@0 | 76 | 
| Asa@0 | 77 	-- See the note in Constructor() for each scroll related function | 
| Asa@0 | 78 	local function OnMouseWheel(this, value) | 
| Asa@0 | 79 		this.obj:MoveScroll(value) | 
| Asa@0 | 80 	end | 
| Asa@0 | 81 | 
| Asa@0 | 82 	local function OnScrollValueChanged(this, value) | 
| Asa@0 | 83 		this.obj:SetScroll(value) | 
| Asa@0 | 84 	end | 
| Asa@0 | 85 | 
| Asa@0 | 86 	local function OnSizeChanged(this) | 
| Asa@0 | 87 		this.obj:FixScroll() | 
| Asa@0 | 88 	end | 
| Asa@0 | 89 | 
| Asa@0 | 90 	--[[ Exported methods ]]-- | 
| Asa@0 | 91 | 
| Asa@0 | 92 	-- exported | 
| Asa@0 | 93 	local function SetScroll(self, value) | 
| Asa@0 | 94 		local status = self.scrollStatus | 
| Asa@0 | 95 		local frame, child = self.scrollFrame, self.itemFrame | 
| Asa@0 | 96 		local height, viewheight = frame:GetHeight(), child:GetHeight() | 
| Asa@0 | 97 | 
| Asa@0 | 98 		local offset | 
| Asa@0 | 99 		if height > viewheight then | 
| Asa@0 | 100 			offset = 0 | 
| Asa@0 | 101 		else | 
| Asa@0 | 102 			offset = floor((viewheight - height) / 1000 * value) | 
| Asa@0 | 103 		end | 
| Asa@0 | 104 		child:ClearAllPoints() | 
| Asa@0 | 105 		child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset) | 
| Asa@0 | 106 		child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", self.slider:IsShown() and -12 or 0, offset) | 
| Asa@0 | 107 		status.offset = offset | 
| Asa@0 | 108 		status.scrollvalue = value | 
| Asa@0 | 109 	end | 
| Asa@0 | 110 | 
| Asa@0 | 111 	-- exported | 
| Asa@0 | 112 	local function MoveScroll(self, value) | 
| Asa@0 | 113 		local status = self.scrollStatus | 
| Asa@0 | 114 		local frame, child = self.scrollFrame, self.itemFrame | 
| Asa@0 | 115 		local height, viewheight = frame:GetHeight(), child:GetHeight() | 
| Asa@0 | 116 | 
| Asa@0 | 117 		if height > viewheight then | 
| Asa@0 | 118 			self.slider:Hide() | 
| Asa@0 | 119 		else | 
| Asa@0 | 120 			self.slider:Show() | 
| Asa@0 | 121 			local diff = height - viewheight | 
| Asa@0 | 122 			local delta = 1 | 
| Asa@0 | 123 			if value < 0 then | 
| Asa@0 | 124 				delta = -1 | 
| Asa@0 | 125 			end | 
| Asa@0 | 126 			self.slider:SetValue(min(max(status.scrollvalue + delta*(1000/(diff/45)),0), 1000)) | 
| Asa@0 | 127 		end | 
| Asa@0 | 128 	end | 
| Asa@0 | 129 | 
| Asa@0 | 130 	-- exported | 
| Asa@0 | 131 	local function FixScroll(self) | 
| Asa@0 | 132 		local status = self.scrollStatus | 
| Asa@0 | 133 		local frame, child = self.scrollFrame, self.itemFrame | 
| Asa@0 | 134 		local height, viewheight = frame:GetHeight(), child:GetHeight() | 
| Asa@0 | 135 		local offset = status.offset or 0 | 
| Asa@0 | 136 | 
| Asa@0 | 137 		if viewheight < height then | 
| Asa@0 | 138 			self.slider:Hide() | 
| Asa@0 | 139 			child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, offset) | 
| Asa@0 | 140 			self.slider:SetValue(0) | 
| Asa@0 | 141 		else | 
| Asa@0 | 142 			self.slider:Show() | 
| Asa@0 | 143 			local value = (offset / (viewheight - height) * 1000) | 
| Asa@0 | 144 			if value > 1000 then value = 1000 end | 
| Asa@0 | 145 			self.slider:SetValue(value) | 
| Asa@0 | 146 			self:SetScroll(value) | 
| Asa@0 | 147 			if value < 1000 then | 
| Asa@0 | 148 				child:ClearAllPoints() | 
| Asa@0 | 149 				child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset) | 
| Asa@0 | 150 				child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -12, offset) | 
| Asa@0 | 151 				status.offset = offset | 
| Asa@0 | 152 			end | 
| Asa@0 | 153 		end | 
| Asa@0 | 154 	end | 
| Asa@0 | 155 | 
| Asa@0 | 156 	-- exported, AceGUI callback | 
| Asa@0 | 157 	local function OnAcquire(self) | 
| Asa@0 | 158 		self.frame:SetParent(UIParent) | 
| Asa@0 | 159 		--self.itemFrame:SetToplevel(true) | 
| Asa@0 | 160 	end | 
| Asa@0 | 161 | 
| Asa@0 | 162 	-- exported, AceGUI callback | 
| Asa@0 | 163 	local function OnRelease(self) | 
| Asa@0 | 164 		self:Clear() | 
| Asa@0 | 165 		self.frame:ClearAllPoints() | 
| Asa@0 | 166 		self.frame:Hide() | 
| Asa@0 | 167 	end | 
| Asa@0 | 168 | 
| Asa@0 | 169 	-- exported | 
| Asa@0 | 170 	local function AddItem(self, item) | 
| Asa@0 | 171 		self.items[#self.items + 1] = item | 
| Asa@0 | 172 | 
| Asa@0 | 173 		local h = #self.items * 16 | 
| Asa@0 | 174 		self.itemFrame:SetHeight(h) | 
| Asa@0 | 175 		self.frame:SetHeight(min(h + 34, self.maxHeight)) -- +34: 20 for scrollFrame placement (10 offset) and +14 for item placement | 
| Asa@0 | 176 | 
| Asa@0 | 177 		item.frame:SetPoint("LEFT", self.itemFrame, "LEFT") | 
| Asa@0 | 178 		item.frame:SetPoint("RIGHT", self.itemFrame, "RIGHT") | 
| Asa@0 | 179 | 
| Asa@0 | 180 		item:SetPullout(self) | 
| Asa@0 | 181 		item:SetOnEnter(OnEnter) | 
| Asa@0 | 182 	end | 
| Asa@0 | 183 | 
| Asa@0 | 184 	-- exported | 
| Asa@0 | 185 	local function Open(self, point, relFrame, relPoint, x, y) | 
| Asa@0 | 186 		local items = self.items | 
| Asa@0 | 187 		local frame = self.frame | 
| Asa@0 | 188 		local itemFrame = self.itemFrame | 
| Asa@0 | 189 | 
| Asa@0 | 190 		frame:SetPoint(point, relFrame, relPoint, x, y) | 
| Asa@0 | 191 | 
| Asa@0 | 192 | 
| Asa@0 | 193 		local height = 8 | 
| Asa@0 | 194 		for i, item in pairs(items) do | 
| Asa@0 | 195 			if i == 1 then | 
| Asa@0 | 196 				item:SetPoint("TOP", itemFrame, "TOP", 0, -2) | 
| Asa@0 | 197 			else | 
| Asa@0 | 198 				item:SetPoint("TOP", items[i-1].frame, "BOTTOM", 0, 1) | 
| Asa@0 | 199 			end | 
| Asa@0 | 200 | 
| Asa@0 | 201 			item:Show() | 
| Asa@0 | 202 | 
| Asa@0 | 203 			height = height + 16 | 
| Asa@0 | 204 		end | 
| Asa@0 | 205 		itemFrame:SetHeight(height) | 
| Asa@0 | 206 		fixstrata("TOOLTIP", frame, frame:GetChildren()) | 
| Asa@0 | 207 		frame:Show() | 
| Asa@0 | 208 		self:Fire("OnOpen") | 
| Asa@0 | 209 	end | 
| Asa@0 | 210 | 
| Asa@0 | 211 	-- exported | 
| Asa@0 | 212 	local function Close(self) | 
| Asa@0 | 213 		self.frame:Hide() | 
| Asa@0 | 214 		self:Fire("OnClose") | 
| Asa@0 | 215 	end | 
| Asa@0 | 216 | 
| Asa@0 | 217 	-- exported | 
| Asa@0 | 218 	local function Clear(self) | 
| Asa@0 | 219 		local items = self.items | 
| Asa@0 | 220 		for i, item in pairs(items) do | 
| Asa@0 | 221 			AceGUI:Release(item) | 
| Asa@0 | 222 			items[i] = nil | 
| Asa@0 | 223 		end | 
| Asa@0 | 224 	end | 
| Asa@0 | 225 | 
| Asa@0 | 226 	-- exported | 
| Asa@0 | 227 	local function IterateItems(self) | 
| Asa@0 | 228 		return ipairs(self.items) | 
| Asa@0 | 229 	end | 
| Asa@0 | 230 | 
| Asa@0 | 231 	-- exported | 
| Asa@0 | 232 	local function SetHideOnLeave(self, val) | 
| Asa@0 | 233 		self.hideOnLeave = val | 
| Asa@0 | 234 	end | 
| Asa@0 | 235 | 
| Asa@0 | 236 	-- exported | 
| Asa@0 | 237 	local function SetMaxHeight(self, height) | 
| Asa@0 | 238 		self.maxHeight = height or defaultMaxHeight | 
| Asa@0 | 239 		if self.frame:GetHeight() > height then | 
| Asa@0 | 240 			self.frame:SetHeight(height) | 
| Asa@0 | 241 		elseif (self.itemFrame:GetHeight() + 34) < height then | 
| Asa@0 | 242 			self.frame:SetHeight(self.itemFrame:GetHeight() + 34) -- see :AddItem | 
| Asa@0 | 243 		end | 
| Asa@0 | 244 	end | 
| Asa@0 | 245 | 
| Asa@0 | 246 	-- exported | 
| Asa@0 | 247 	local function GetRightBorderWidth(self) | 
| Asa@0 | 248 		return 6 + (self.slider:IsShown() and 12 or 0) | 
| Asa@0 | 249 	end | 
| Asa@0 | 250 | 
| Asa@0 | 251 	-- exported | 
| Asa@0 | 252 	local function GetLeftBorderWidth(self) | 
| Asa@0 | 253 		return 6 | 
| Asa@0 | 254 	end | 
| Asa@0 | 255 | 
| Asa@0 | 256 	--[[ Constructor ]]-- | 
| Asa@0 | 257 | 
| Asa@0 | 258 	local function Constructor() | 
| Asa@0 | 259 		local count = AceGUI:GetNextWidgetNum(widgetType) | 
| Asa@0 | 260 		local frame = CreateFrame("Frame", "AceGUI30Pullout"..count, UIParent) | 
| Asa@0 | 261 		local self = {} | 
| Asa@0 | 262 		self.count = count | 
| Asa@0 | 263 		self.type = widgetType | 
| Asa@0 | 264 		self.frame = frame | 
| Asa@0 | 265 		frame.obj = self | 
| Asa@0 | 266 | 
| Asa@0 | 267 		self.OnAcquire = OnAcquire | 
| Asa@0 | 268 		self.OnRelease = OnRelease | 
| Asa@0 | 269 | 
| Asa@0 | 270 		self.AddItem = AddItem | 
| Asa@0 | 271 		self.Open    = Open | 
| Asa@0 | 272 		self.Close   = Close | 
| Asa@0 | 273 		self.Clear   = Clear | 
| Asa@0 | 274 		self.IterateItems = IterateItems | 
| Asa@0 | 275 		self.SetHideOnLeave = SetHideOnLeave | 
| Asa@0 | 276 | 
| Asa@0 | 277 		self.SetScroll  = SetScroll | 
| Asa@0 | 278 		self.MoveScroll = MoveScroll | 
| Asa@0 | 279 		self.FixScroll  = FixScroll | 
| Asa@0 | 280 | 
| Asa@0 | 281 		self.SetMaxHeight = SetMaxHeight | 
| Asa@0 | 282 		self.GetRightBorderWidth = GetRightBorderWidth | 
| Asa@0 | 283 		self.GetLeftBorderWidth = GetLeftBorderWidth | 
| Asa@0 | 284 | 
| Asa@0 | 285 		self.items = {} | 
| Asa@0 | 286 | 
| Asa@0 | 287 		self.scrollStatus = { | 
| Asa@0 | 288 			scrollvalue = 0, | 
| Asa@0 | 289 		} | 
| Asa@0 | 290 | 
| Asa@0 | 291 		self.maxHeight = defaultMaxHeight | 
| Asa@0 | 292 | 
| Asa@0 | 293 		frame:SetBackdrop(backdrop) | 
| Asa@0 | 294 		frame:SetBackdropColor(0, 0, 0) | 
| Asa@0 | 295 		frame:SetFrameStrata("FULLSCREEN_DIALOG") | 
| Asa@0 | 296 		frame:SetClampedToScreen(true) | 
| Asa@0 | 297 		frame:SetWidth(defaultWidth) | 
| Asa@0 | 298 		frame:SetHeight(self.maxHeight) | 
| Asa@0 | 299 		--frame:SetToplevel(true) | 
| Asa@0 | 300 | 
| Asa@0 | 301 		-- NOTE: The whole scroll frame code is copied from the AceGUI-3.0 widget ScrollFrame | 
| Asa@0 | 302 		local scrollFrame = CreateFrame("ScrollFrame", nil, frame) | 
| Asa@0 | 303 		local itemFrame = CreateFrame("Frame", nil, scrollFrame) | 
| Asa@0 | 304 | 
| Asa@0 | 305 		self.scrollFrame = scrollFrame | 
| Asa@0 | 306 		self.itemFrame = itemFrame | 
| Asa@0 | 307 | 
| Asa@0 | 308 		scrollFrame.obj = self | 
| Asa@0 | 309 		itemFrame.obj = self | 
| Asa@0 | 310 | 
| Asa@0 | 311 		local slider = CreateFrame("Slider", "AceGUI30PulloutScrollbar"..count, scrollFrame) | 
| Asa@0 | 312 		slider:SetOrientation("VERTICAL") | 
| Asa@0 | 313 		slider:SetHitRectInsets(0, 0, -10, 0) | 
| Asa@0 | 314 		slider:SetBackdrop(sliderBackdrop) | 
| Asa@0 | 315 		slider:SetWidth(8) | 
| Asa@0 | 316 		slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical") | 
| Asa@0 | 317 		slider:SetFrameStrata("FULLSCREEN_DIALOG") | 
| Asa@0 | 318 		self.slider = slider | 
| Asa@0 | 319 		slider.obj = self | 
| Asa@0 | 320 | 
| Asa@0 | 321 		scrollFrame:SetScrollChild(itemFrame) | 
| Asa@0 | 322 		scrollFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 6, -12) | 
| Asa@0 | 323 		scrollFrame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -6, 12) | 
| Asa@0 | 324 		scrollFrame:EnableMouseWheel(true) | 
| Asa@0 | 325 		scrollFrame:SetScript("OnMouseWheel", OnMouseWheel) | 
| Asa@0 | 326 		scrollFrame:SetScript("OnSizeChanged", OnSizeChanged) | 
| Asa@0 | 327 		scrollFrame:SetToplevel(true) | 
| Asa@0 | 328 		scrollFrame:SetFrameStrata("FULLSCREEN_DIALOG") | 
| Asa@0 | 329 | 
| Asa@0 | 330 		itemFrame:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT", 0, 0) | 
| Asa@0 | 331 		itemFrame:SetPoint("TOPRIGHT", scrollFrame, "TOPRIGHT", -12, 0) | 
| Asa@0 | 332 		itemFrame:SetHeight(400) | 
| Asa@0 | 333 		itemFrame:SetToplevel(true) | 
| Asa@0 | 334 		itemFrame:SetFrameStrata("FULLSCREEN_DIALOG") | 
| Asa@0 | 335 | 
| Asa@0 | 336 		slider:SetPoint("TOPLEFT", scrollFrame, "TOPRIGHT", -16, 0) | 
| Asa@0 | 337 		slider:SetPoint("BOTTOMLEFT", scrollFrame, "BOTTOMRIGHT", -16, 0) | 
| Asa@0 | 338 		slider:SetScript("OnValueChanged", OnScrollValueChanged) | 
| Asa@0 | 339 		slider:SetMinMaxValues(0, 1000) | 
| Asa@0 | 340 		slider:SetValueStep(1) | 
| Asa@0 | 341 		slider:SetValue(0) | 
| Asa@0 | 342 | 
| Asa@0 | 343 		scrollFrame:Show() | 
| Asa@0 | 344 		itemFrame:Show() | 
| Asa@0 | 345 		slider:Hide() | 
| Asa@0 | 346 | 
| Asa@0 | 347 		self:FixScroll() | 
| Asa@0 | 348 | 
| Asa@0 | 349 		AceGUI:RegisterAsWidget(self) | 
| Asa@0 | 350 		return self | 
| Asa@0 | 351 	end | 
| Asa@0 | 352 | 
| Asa@0 | 353 	AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion) | 
| Asa@0 | 354 end | 
| Asa@0 | 355 | 
| Asa@0 | 356 do | 
| Asa@0 | 357 	local widgetType = "Dropdown" | 
| Asa@0 | 358 	local widgetVersion = 21 | 
| Asa@0 | 359 | 
| Asa@0 | 360 	--[[ Static data ]]-- | 
| Asa@0 | 361 | 
| Asa@0 | 362 	--[[ UI event handler ]]-- | 
| Asa@0 | 363 | 
| Asa@0 | 364 	local function Control_OnEnter(this) | 
| Asa@0 | 365 		this.obj:Fire("OnEnter") | 
| Asa@0 | 366 	end | 
| Asa@0 | 367 | 
| Asa@0 | 368 	local function Control_OnLeave(this) | 
| Asa@0 | 369 		this.obj:Fire("OnLeave") | 
| Asa@0 | 370 	end | 
| Asa@0 | 371 | 
| Asa@0 | 372 	local function Dropdown_OnHide(this) | 
| Asa@0 | 373 		local self = this.obj | 
| Asa@0 | 374 		if self.open then | 
| Asa@0 | 375 			self.pullout:Close() | 
| Asa@0 | 376 		end | 
| Asa@0 | 377 	end | 
| Asa@0 | 378 | 
| Asa@0 | 379 	local function Dropdown_TogglePullout(this) | 
| Asa@0 | 380 		local self = this.obj | 
| Asa@0 | 381 		if self.open then | 
| Asa@0 | 382 			self.open = nil | 
| Asa@0 | 383 			self.pullout:Close() | 
| Asa@0 | 384 			AceGUI:ClearFocus() | 
| Asa@0 | 385 		else | 
| Asa@0 | 386 			self.open = true | 
| Asa@0 | 387 			self.pullout:SetWidth(self.frame:GetWidth()) | 
| Asa@0 | 388 			self.pullout:Open("TOPLEFT", self.frame, "BOTTOMLEFT", 0, self.label:IsShown() and -2 or 0) | 
| Asa@0 | 389 			AceGUI:SetFocus(self) | 
| Asa@0 | 390 		end | 
| Asa@0 | 391 	end | 
| Asa@0 | 392 | 
| Asa@0 | 393 	local function OnPulloutOpen(this) | 
| Asa@0 | 394 		local self = this.userdata.obj | 
| Asa@0 | 395 		local value = self.value | 
| Asa@0 | 396 | 
| Asa@0 | 397 		if not self.multiselect then | 
| Asa@0 | 398 			for i, item in this:IterateItems() do | 
| Asa@0 | 399 				item:SetValue(item.userdata.value == value) | 
| Asa@0 | 400 			end | 
| Asa@0 | 401 		end | 
| Asa@0 | 402 | 
| Asa@0 | 403 		self.open = true | 
| Asa@0 | 404 	end | 
| Asa@0 | 405 | 
| Asa@0 | 406 	local function OnPulloutClose(this) | 
| Asa@0 | 407 		local self = this.userdata.obj | 
| Asa@0 | 408 		self.open = nil | 
| Asa@0 | 409 		self:Fire("OnClosed") | 
| Asa@0 | 410 	end | 
| Asa@0 | 411 | 
| Asa@0 | 412 	local function ShowMultiText(self) | 
| Asa@0 | 413 		local text | 
| Asa@0 | 414 		for i, widget in self.pullout:IterateItems() do | 
| Asa@0 | 415 			if widget.type == "Dropdown-Item-Toggle" then | 
| Asa@0 | 416 				if widget:GetValue() then | 
| Asa@0 | 417 					if text then | 
| Asa@0 | 418 						text = text..", "..widget:GetText() | 
| Asa@0 | 419 					else | 
| Asa@0 | 420 						text = widget:GetText() | 
| Asa@0 | 421 					end | 
| Asa@0 | 422 				end | 
| Asa@0 | 423 			end | 
| Asa@0 | 424 		end | 
| Asa@0 | 425 		self:SetText(text) | 
| Asa@0 | 426 	end | 
| Asa@0 | 427 | 
| Asa@0 | 428 	local function OnItemValueChanged(this, event, checked) | 
| Asa@0 | 429 		local self = this.userdata.obj | 
| Asa@0 | 430 | 
| Asa@0 | 431 		if self.multiselect then | 
| Asa@0 | 432 			self:Fire("OnValueChanged", this.userdata.value, checked) | 
| Asa@0 | 433 			ShowMultiText(self) | 
| Asa@0 | 434 		else | 
| Asa@0 | 435 			if checked then | 
| Asa@0 | 436 				self:SetValue(this.userdata.value) | 
| Asa@0 | 437 				self:Fire("OnValueChanged", this.userdata.value) | 
| Asa@0 | 438 			else | 
| Asa@0 | 439 				this:SetValue(true) | 
| Asa@0 | 440 			end | 
| Asa@0 | 441 			if self.open then | 
| Asa@0 | 442 				self.pullout:Close() | 
| Asa@0 | 443 			end | 
| Asa@0 | 444 		end | 
| Asa@0 | 445 	end | 
| Asa@0 | 446 | 
| Asa@0 | 447 	--[[ Exported methods ]]-- | 
| Asa@0 | 448 | 
| Asa@0 | 449 	-- exported, AceGUI callback | 
| Asa@0 | 450 	local function OnAcquire(self) | 
| Asa@0 | 451 		local pullout = AceGUI:Create("Dropdown-Pullout") | 
| Asa@0 | 452 		self.pullout = pullout | 
| Asa@0 | 453 		pullout.userdata.obj = self | 
| Asa@0 | 454 		pullout:SetCallback("OnClose", OnPulloutClose) | 
| Asa@0 | 455 		pullout:SetCallback("OnOpen", OnPulloutOpen) | 
| Asa@0 | 456 		self.pullout.frame:SetFrameLevel(self.frame:GetFrameLevel() + 1) | 
| Asa@0 | 457 		fixlevels(self.pullout.frame, self.pullout.frame:GetChildren()) | 
| Asa@0 | 458 | 
| Asa@0 | 459 		self:SetHeight(44) | 
| Asa@0 | 460 		self:SetWidth(200) | 
| Asa@0 | 461 	end | 
| Asa@0 | 462 | 
| Asa@0 | 463 	-- exported, AceGUI callback | 
| Asa@0 | 464 	local function OnRelease(self) | 
| Asa@0 | 465 		if self.open then | 
| Asa@0 | 466 			self.pullout:Close() | 
| Asa@0 | 467 		end | 
| Asa@0 | 468 		AceGUI:Release(self.pullout) | 
| Asa@0 | 469 		self.pullout = nil | 
| Asa@0 | 470 | 
| Asa@0 | 471 		self:SetText("") | 
| Asa@0 | 472 		self:SetLabel("") | 
| Asa@0 | 473 		self:SetDisabled(false) | 
| Asa@0 | 474 		self:SetMultiselect(false) | 
| Asa@0 | 475 | 
| Asa@0 | 476 		self.value = nil | 
| Asa@0 | 477 		self.list = nil | 
| Asa@0 | 478 		self.open = nil | 
| Asa@0 | 479 		self.hasClose = nil | 
| Asa@0 | 480 | 
| Asa@0 | 481 		self.frame:ClearAllPoints() | 
| Asa@0 | 482 		self.frame:Hide() | 
| Asa@0 | 483 	end | 
| Asa@0 | 484 | 
| Asa@0 | 485 	-- exported | 
| Asa@0 | 486 	local function SetDisabled(self, disabled) | 
| Asa@0 | 487 		self.disabled = disabled | 
| Asa@0 | 488 		if disabled then | 
| Asa@0 | 489 			self.text:SetTextColor(0.5,0.5,0.5) | 
| Asa@0 | 490 			self.button:Disable() | 
| Asa@0 | 491 			self.label:SetTextColor(0.5,0.5,0.5) | 
| Asa@0 | 492 		else | 
| Asa@0 | 493 			self.button:Enable() | 
| Asa@0 | 494 			self.label:SetTextColor(1,.82,0) | 
| Asa@0 | 495 			self.text:SetTextColor(1,1,1) | 
| Asa@0 | 496 		end | 
| Asa@0 | 497 	end | 
| Asa@0 | 498 | 
| Asa@0 | 499 	-- exported | 
| Asa@0 | 500 	local function ClearFocus(self) | 
| Asa@0 | 501 		if self.open then | 
| Asa@0 | 502 			self.pullout:Close() | 
| Asa@0 | 503 		end | 
| Asa@0 | 504 	end | 
| Asa@0 | 505 | 
| Asa@0 | 506 	-- exported | 
| Asa@0 | 507 	local function SetText(self, text) | 
| Asa@0 | 508 		self.text:SetText(text or "") | 
| Asa@0 | 509 	end | 
| Asa@0 | 510 | 
| Asa@0 | 511 	-- exported | 
| Asa@0 | 512 	local function SetLabel(self, text) | 
| Asa@0 | 513 		if text and text ~= "" then | 
| Asa@0 | 514 			self.label:SetText(text) | 
| Asa@0 | 515 			self.label:Show() | 
| Asa@0 | 516 			self.dropdown:SetPoint("TOPLEFT",self.frame,"TOPLEFT",-15,-18) | 
| Asa@0 | 517 			self.frame:SetHeight(44) | 
| Asa@0 | 518 		else | 
| Asa@0 | 519 			self.label:SetText("") | 
| Asa@0 | 520 			self.label:Hide() | 
| Asa@0 | 521 			self.dropdown:SetPoint("TOPLEFT",self.frame,"TOPLEFT",-15,0) | 
| Asa@0 | 522 			self.frame:SetHeight(26) | 
| Asa@0 | 523 		end | 
| Asa@0 | 524 	end | 
| Asa@0 | 525 | 
| Asa@0 | 526 	-- exported | 
| Asa@0 | 527 	local function SetValue(self, value) | 
| Asa@0 | 528 		if self.list then | 
| Asa@0 | 529 			self:SetText(self.list[value] or "") | 
| Asa@0 | 530 		end | 
| Asa@0 | 531 		self.value = value | 
| Asa@0 | 532 	end | 
| Asa@0 | 533 | 
| Asa@0 | 534 	-- exported | 
| Asa@0 | 535 	local function GetValue(self) | 
| Asa@0 | 536 		return self.value | 
| Asa@0 | 537 	end | 
| Asa@0 | 538 | 
| Asa@0 | 539 	-- exported | 
| Asa@0 | 540 	local function SetItemValue(self, item, value) | 
| Asa@0 | 541 		if not self.multiselect then return end | 
| Asa@0 | 542 		for i, widget in self.pullout:IterateItems() do | 
| Asa@0 | 543 			if widget.userdata.value == item then | 
| Asa@0 | 544 				if widget.SetValue then | 
| Asa@0 | 545 					widget:SetValue(value) | 
| Asa@0 | 546 				end | 
| Asa@0 | 547 			end | 
| Asa@0 | 548 		end | 
| Asa@0 | 549 		ShowMultiText(self) | 
| Asa@0 | 550 	end | 
| Asa@0 | 551 | 
| Asa@0 | 552 	-- exported | 
| Asa@0 | 553 	local function SetItemDisabled(self, item, disabled) | 
| Asa@0 | 554 		for i, widget in self.pullout:IterateItems() do | 
| Asa@0 | 555 			if widget.userdata.value == item then | 
| Asa@0 | 556 				widget:SetDisabled(disabled) | 
| Asa@0 | 557 			end | 
| Asa@0 | 558 		end | 
| Asa@0 | 559 	end | 
| Asa@0 | 560 | 
| Asa@0 | 561 	local function AddListItem(self, value, text) | 
| Asa@0 | 562 		local item = AceGUI:Create("Dropdown-Item-Toggle") | 
| Asa@0 | 563 		item:SetText(text) | 
| Asa@0 | 564 		item.userdata.obj = self | 
| Asa@0 | 565 		item.userdata.value = value | 
| Asa@0 | 566 		item:SetCallback("OnValueChanged", OnItemValueChanged) | 
| Asa@0 | 567 		self.pullout:AddItem(item) | 
| Asa@0 | 568 	end | 
| Asa@0 | 569 | 
| Asa@0 | 570 	local function AddCloseButton(self) | 
| Asa@0 | 571 		if not self.hasClose then | 
| Asa@0 | 572 			local close = AceGUI:Create("Dropdown-Item-Execute") | 
| Asa@0 | 573 			close:SetText(CLOSE) | 
| Asa@0 | 574 			self.pullout:AddItem(close) | 
| Asa@0 | 575 			self.hasClose = true | 
| Asa@0 | 576 		end | 
| Asa@0 | 577 	end | 
| Asa@0 | 578 | 
| Asa@0 | 579 	-- exported | 
| Asa@0 | 580 	local sortlist = {} | 
| Asa@0 | 581 	local function SetList(self, list) | 
| Asa@0 | 582 		self.list = list | 
| Asa@0 | 583 		self.pullout:Clear() | 
| Asa@0 | 584 		self.hasClose = nil | 
| Asa@0 | 585 		if not list then return end | 
| Asa@0 | 586 | 
| Asa@0 | 587 		for v in pairs(list) do | 
| Asa@0 | 588 			sortlist[#sortlist + 1] = v | 
| Asa@0 | 589 		end | 
| Asa@0 | 590 		tsort(sortlist) | 
| Asa@0 | 591 | 
| Asa@0 | 592 		for i, value in pairs(sortlist) do | 
| Asa@0 | 593 			AddListItem(self, value, list[value]) | 
| Asa@0 | 594 			sortlist[i] = nil | 
| Asa@0 | 595 		end | 
| Asa@0 | 596 		if self.multiselect then | 
| Asa@0 | 597 			ShowMultiText(self) | 
| Asa@0 | 598 			AddCloseButton(self) | 
| Asa@0 | 599 		end | 
| Asa@0 | 600 	end | 
| Asa@0 | 601 | 
| Asa@0 | 602 	-- exported | 
| Asa@0 | 603 	local function AddItem(self, value, text) | 
| Asa@0 | 604 		if self.list then | 
| Asa@0 | 605 			self.list[value] = text | 
| Asa@0 | 606 			AddListItem(self, value, text) | 
| Asa@0 | 607 		end | 
| Asa@0 | 608 	end | 
| Asa@0 | 609 | 
| Asa@0 | 610 	-- exported | 
| Asa@0 | 611 	local function SetMultiselect(self, multi) | 
| Asa@0 | 612 		self.multiselect = multi | 
| Asa@0 | 613 		if multi then | 
| Asa@0 | 614 			ShowMultiText(self) | 
| Asa@0 | 615 			AddCloseButton(self) | 
| Asa@0 | 616 		end | 
| Asa@0 | 617 	end | 
| Asa@0 | 618 | 
| Asa@0 | 619 	-- exported | 
| Asa@0 | 620 	local function GetMultiselect(self) | 
| Asa@0 | 621 		return self.multiselect | 
| Asa@0 | 622 	end | 
| Asa@0 | 623 | 
| Asa@0 | 624 	--[[ Constructor ]]-- | 
| Asa@0 | 625 | 
| Asa@0 | 626 	local function Constructor() | 
| Asa@0 | 627 		local count = AceGUI:GetNextWidgetNum(widgetType) | 
| Asa@0 | 628 		local frame = CreateFrame("Frame", nil, UIParent) | 
| Asa@0 | 629 		local dropdown = CreateFrame("Frame", "AceGUI30DropDown"..count, frame, "UIDropDownMenuTemplate") | 
| Asa@0 | 630 | 
| Asa@0 | 631 		local self = {} | 
| Asa@0 | 632 		self.type = widgetType | 
| Asa@0 | 633 		self.frame = frame | 
| Asa@0 | 634 		self.dropdown = dropdown | 
| Asa@0 | 635 		self.count = count | 
| Asa@0 | 636 		frame.obj = self | 
| Asa@0 | 637 		dropdown.obj = self | 
| Asa@0 | 638 | 
| Asa@0 | 639 		self.OnRelease   = OnRelease | 
| Asa@0 | 640 		self.OnAcquire   = OnAcquire | 
| Asa@0 | 641 | 
| Asa@0 | 642 		self.ClearFocus  = ClearFocus | 
| Asa@0 | 643 | 
| Asa@0 | 644 		self.SetText     = SetText | 
| Asa@0 | 645 		self.SetValue    = SetValue | 
| Asa@0 | 646 		self.GetValue    = GetValue | 
| Asa@0 | 647 		self.SetList     = SetList | 
| Asa@0 | 648 		self.SetLabel    = SetLabel | 
| Asa@0 | 649 		self.SetDisabled = SetDisabled | 
| Asa@0 | 650 		self.AddItem     = AddItem | 
| Asa@0 | 651 		self.SetMultiselect = SetMultiselect | 
| Asa@0 | 652 		self.GetMultiselect = GetMultiselect | 
| Asa@0 | 653 		self.SetItemValue = SetItemValue | 
| Asa@0 | 654 		self.SetItemDisabled = SetItemDisabled | 
| Asa@0 | 655 | 
| Asa@0 | 656 		self.alignoffset = 31 | 
| Asa@0 | 657 | 
| Asa@0 | 658 		frame:SetHeight(44) | 
| Asa@0 | 659 		frame:SetWidth(200) | 
| Asa@0 | 660 		frame:SetScript("OnHide",Dropdown_OnHide) | 
| Asa@0 | 661 | 
| Asa@0 | 662 		dropdown:ClearAllPoints() | 
| Asa@0 | 663 		dropdown:SetPoint("TOPLEFT",frame,"TOPLEFT",-15,0) | 
| Asa@0 | 664 		dropdown:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",17,0) | 
| Asa@0 | 665 		dropdown:SetScript("OnHide", nil) | 
| Asa@0 | 666 | 
| Asa@0 | 667 		local left = _G[dropdown:GetName() .. "Left"] | 
| Asa@0 | 668 		local middle = _G[dropdown:GetName() .. "Middle"] | 
| Asa@0 | 669 		local right = _G[dropdown:GetName() .. "Right"] | 
| Asa@0 | 670 | 
| Asa@0 | 671 		middle:ClearAllPoints() | 
| Asa@0 | 672 		right:ClearAllPoints() | 
| Asa@0 | 673 | 
| Asa@0 | 674 		middle:SetPoint("LEFT", left, "RIGHT", 0, 0) | 
| Asa@0 | 675 		middle:SetPoint("RIGHT", right, "LEFT", 0, 0) | 
| Asa@0 | 676 		right:SetPoint("TOPRIGHT", dropdown, "TOPRIGHT", 0, 17) | 
| Asa@0 | 677 | 
| Asa@0 | 678 		local button = _G[dropdown:GetName() .. "Button"] | 
| Asa@0 | 679 		self.button = button | 
| Asa@0 | 680 		button.obj = self | 
| Asa@0 | 681 		button:SetScript("OnEnter",Control_OnEnter) | 
| Asa@0 | 682 		button:SetScript("OnLeave",Control_OnLeave) | 
| Asa@0 | 683 		button:SetScript("OnClick",Dropdown_TogglePullout) | 
| Asa@0 | 684 | 
| Asa@0 | 685 		local text = _G[dropdown:GetName() .. "Text"] | 
| Asa@0 | 686 		self.text = text | 
| Asa@0 | 687 		text.obj = self | 
| Asa@0 | 688 		text:ClearAllPoints() | 
| Asa@0 | 689 		text:SetPoint("RIGHT", right, "RIGHT" ,-43, 2) | 
| Asa@0 | 690 		text:SetPoint("LEFT", left, "LEFT", 25, 2) | 
| Asa@0 | 691 | 
| Asa@0 | 692 		local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall") | 
| Asa@0 | 693 		label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0) | 
| Asa@0 | 694 		label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0) | 
| Asa@0 | 695 		label:SetJustifyH("LEFT") | 
| Asa@0 | 696 		label:SetHeight(18) | 
| Asa@0 | 697 		label:Hide() | 
| Asa@0 | 698 		self.label = label | 
| Asa@0 | 699 | 
| Asa@0 | 700 		AceGUI:RegisterAsWidget(self) | 
| Asa@0 | 701 		return self | 
| Asa@0 | 702 	end | 
| Asa@0 | 703 | 
| Asa@0 | 704 	AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion) | 
| Asa@0 | 705 end |