Mercurial > wow > ouroloot
view AceGUIWidget-DoTimerEditBoxDropDown.lua @ 11:952c3ac0e783
GetItemQualityColor change and TOC bump for 4.2
author | Farmbuyer of US-Kilrogg <farmbuyer@gmail.com> |
---|---|
date | Tue, 28 Jun 2011 19:18:07 +0000 |
parents | 822b6ca3ef89 |
children | 6d5fcbdc0590 |
line wrap: on
line source
local Type, Version = "EditBoxDropDown", 3 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end --[[ This is a from-scratch AceGUI-style implementation of the combination drop- down editboxes seen in DoTimer's option menus. Typing in the editbox adds entries to a list; clicking the scrolldown button displays the list in a dropdown; clicking on an entry in the dropdown removes it from the list. (This type of widget may actually have a more formal name already. I first encountered it in DoTimer, so that's what I named it after.) The implementation does not borrow any of DoTimer's actual code. I've tried writing this to imitate the look-and-feel of an interface that many players will find familiar and easy to use. Version 2 is a rehash to follow the same form of the rest of the AceGUI widgets after their rewrite, and to work with the new EditBox behavior. Version 3 adds the EditBoxDropDownOptionControl variant, specifically for use as a 'dialogControl' in AceConfig option tables. Details follow; the more disappointing restrictions are because AceConfig never gives the end user any direct link to the widgets in use. - 'desc' option field ignored - 'name' field may contain an embedded tab ('\t') followed by more text to be used as the tooltip text when hovering over the editbox field - 'get' field must be a function, returning a function to be used as the OnTextEnterPressed callback; this is typically how new entries should be added to data - 'values' field must be a function, returning the usual list of entries, PLUS the callback used for 'get', e.g., values = function() local ret = build_real_dropdown_values() ret[get_callback] = true -- assuming "function get_callback (widget, event, text)" return ret end The callback will be immediately removed from the table, but is required to be present to pass tests in the AceConfig source. - 'set' receives the key of the dropdown table, but that entry will already be removed by the time the 'set' function is called EditBoxDropDown API :SetLabel(txt) forwards to the editbox's SetLabel :SetText(txt) forwards to the editbox's SetText :SetEditBoxTooltip(txt) sets text for the tooltip shown when hovering over the editbox no default :SetButtonTooltip(txt) sets text for the tooltip shown when hovering over the dropdown button default "Click on entries to remove them." :SetList(t) T is a table to be shown in the dropdown list; the values will be displayed in the dropdown When entries are clicked, they will be removed from T. T is not copied, the table is edited "live" before firing the callback below. EditBoxDropDown Callbacks OnTextEnterPressed same as the editbox's OnEnterPressed OnListItemClicked similar to a Dropdown widget's OnValueChanged, the key and value from the table given to :SetList are passed farmbuyer ]] local button_hover_text_default = "Click on entries to remove them." local maps -- from actual editbox frame back to this widget local function Menu_OnClick (button, userlist_key, widget) local v = widget.list[userlist_key] widget.list[userlist_key] = nil widget.dropdown.is_on = nil -- firing these off changes widget contents, must be done last :-( widget:Fire("OnListItemClicked", userlist_key, v) widget:Fire("OnValueChanged", userlist_key) end local function BuildList (widget) local ret = {} if widget.list then for k,v in pairs(widget.list) do table.insert (ret, { text = tostring(v) or tostring(k), func = Menu_OnClick, arg1 = k, arg2 = widget, notCheckable = true, }) end end return ret end local function ddEditBox_OnMouseEnter (editbox) if editbox.tooltip_text then GameTooltip:SetOwner(editbox.frame, "ANCHOR_RIGHT") GameTooltip:SetText(editbox.tooltip_text, nil, nil, nil, nil, 1) end end local function ddEditBox_OnMouseLeave (editbox_or_button) GameTooltip:Hide() end local function ddEditBox_Clear (editboxframe) editboxframe:SetText("") end local function ddEditBox_Reset (editboxframe) -- :ClearFocus triggers this editboxframe:SetText(maps[editboxframe].editbox_basetext or "") end local function ddEditBox_OnEnterPressed (editbox, _, text) editbox.obj:Fire("OnTextEnterPressed", text) ddEditBox_Reset(editbox.editbox) editbox.editbox:ClearFocus() -- cursor still blinking in there, one more time end local function Button_OnClick (button) local dd = button.obj.dropdown -- Annoyingly, it's very tedious to find the correct nested frame to use -- for :IsShown() here. We'll avoid it all by using our own flag. if dd.is_on then dd.is_on = nil HideDropDownMenu(--[[level=]]1) -- EasyMenu always uses top/1 level else dd.is_on = true local t = BuildList(button.obj) EasyMenu (t, button.obj.dropdown, button.obj.frame, 0, 0, "MENU") PlaySound("igMainMenuOptionCheckBoxOn") end end local function Button_OnEnter (button) if button.tooltip_text then GameTooltip:SetOwner(button, "ANCHOR_RIGHT") GameTooltip:SetText(button.tooltip_text, nil, nil, nil, nil, 1) end end local methods = { ["OnAcquire"] = function (self) self:SetHeight(20) self:SetWidth(100) self.button.tooltip_text = button_hover_text_default self:SetList(nil) self.editbox:DisableButton(true) maps = maps or {} maps[self.editbox.editbox] = self end, ["OnRelease"] = function (self) self.frame:ClearAllPoints() self.frame:Hide() self.editbox.tooltip_text = nil self.button.tooltip_text = nil self:SetList(nil) maps[self.editbox.editbox] = nil end, ["SetParent"] = function (self, parent) self.frame:SetParent(nil) self.frame:SetParent(parent.content) self.parent = parent self.editbox:SetParent(parent) end, ["SetText"] = function (self, text) self.editbox_basetext = text return self.editbox:SetText(text) end, ["SetLabel"] = function (self, text) return self.editbox:SetLabel(text) end, ["SetDisabled"] = function (self, disabled) self.editbox:SetDisabled(disabled) if disabled then self.button:Disable() else self.button:Enable() end end, ["SetList"] = function (self, list) self.list = list end, ["SetEditBoxTooltip"] = function (self, text) self.editbox.tooltip_text = text end, ["SetButtonTooltip"] = function (self, text) self.button.tooltip_text = text end, } -- called with the 'name' entry local function optcontrol_SetLabel (self, text) local name, desc = ('\t'):split(text) if desc then self:SetEditBoxTooltip(desc) end self.editbox:SetLabel(name) end local function optcontrol_SetValue (self, epcallback) -- set the callback self:SetCallback("OnTextEnterPressed", epcallback) -- remove the fake entry from the values table self.list[epcallback] = nil end local function Constructor(is_option_control) local num = AceGUI:GetNextWidgetNum(Type) -- Its frame becomes our widget frame, else its frame is never shown. Gluing -- them together seems a little evil, but it beats making this widget into a -- formal containter. Inspired by new-style InteractiveLabel. local editbox = AceGUI:Create("EditBox") local frame = editbox.frame editbox:SetHeight(20) editbox:SetWidth(100) frame:SetWidth(frame:GetWidth()+6) editbox:SetCallback("OnEnter", ddEditBox_OnMouseEnter) editbox:SetCallback("OnLeave", ddEditBox_OnMouseLeave) editbox:SetCallback("OnEnterPressed", ddEditBox_OnEnterPressed) editbox.editbox:SetScript("OnEditFocusGained", ddEditBox_Clear) editbox.editbox:SetScript("OnEditFocusLost", ddEditBox_Reset) --editbox.editbox:SetScript("OnEscapePressed", ddEditBox_Reset) local button = CreateFrame("Button", nil, frame) button:SetHeight(20) button:SetWidth(24) button:SetPoint("LEFT", editbox.frame, "RIGHT", 0, 0) button:SetNormalTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Up") button:SetPushedTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Down") button:SetDisabledTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Disabled") button:SetHighlightTexture("Interface\\Buttons\\UI-Common-MouseHilight","ADD") button:SetScript("OnClick", Button_OnClick) button:SetScript("OnEnter", Button_OnEnter) button:SetScript("OnLeave", ddEditBox_OnMouseLeave) button.parent = frame local dropdown = CreateFrame("Frame", "AceGUI-3.0EditBoxDropDownMenu"..num, nil, "UIDropDownMenuTemplate") dropdown:Hide() local widget = { editbox = editbox, button = button, dropdown = dropdown, frame = frame, type = Type } for method, func in pairs(methods) do widget[method] = func end editbox.obj, button.obj, dropdown.obj = widget, widget, widget if is_option_control then widget.is_option_control = true widget.SetLabel = optcontrol_SetLabel widget.SetValue = optcontrol_SetValue end return AceGUI:RegisterAsWidget(widget) end AceGUI:RegisterWidgetType (Type, Constructor, Version) AceGUI:RegisterWidgetType (Type.."OptionControl", function() return Constructor(true) end, Version)