Mercurial > wow > ouroloot
comparison AceGUIWidget-DoTimerEditBoxDropDown.lua @ 1:822b6ca3ef89
Import of 2.15, moving to wowace svn.
| author | Farmbuyer of US-Kilrogg <farmbuyer@gmail.com> |
|---|---|
| date | Sat, 16 Apr 2011 06:03:29 +0000 |
| parents | |
| children | 6d5fcbdc0590 |
comparison
equal
deleted
inserted
replaced
| 0:0f14a1e5364d | 1:822b6ca3ef89 |
|---|---|
| 1 local Type, Version = "EditBoxDropDown", 3 | |
| 2 local AceGUI = LibStub and LibStub("AceGUI-3.0", true) | |
| 3 if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end | |
| 4 | |
| 5 --[[ | |
| 6 This is a from-scratch AceGUI-style implementation of the combination drop- | |
| 7 down editboxes seen in DoTimer's option menus. Typing in the editbox adds | |
| 8 entries to a list; clicking the scrolldown button displays the list in a | |
| 9 dropdown; clicking on an entry in the dropdown removes it from the list. | |
| 10 | |
| 11 (This type of widget may actually have a more formal name already. I first | |
| 12 encountered it in DoTimer, so that's what I named it after.) | |
| 13 | |
| 14 The implementation does not borrow any of DoTimer's actual code. I've tried | |
| 15 writing this to imitate the look-and-feel of an interface that many players | |
| 16 will find familiar and easy to use. | |
| 17 | |
| 18 Version 2 is a rehash to follow the same form of the rest of the AceGUI widgets | |
| 19 after their rewrite, and to work with the new EditBox behavior. | |
| 20 | |
| 21 Version 3 adds the EditBoxDropDownOptionControl variant, specifically for use | |
| 22 as a 'dialogControl' in AceConfig option tables. Details follow; the more | |
| 23 disappointing restrictions are because AceConfig never gives the end user any | |
| 24 direct link to the widgets in use. | |
| 25 - 'desc' option field ignored | |
| 26 - 'name' field may contain an embedded tab ('\t') followed by more text to be | |
| 27 used as the tooltip text when hovering over the editbox field | |
| 28 - 'get' field must be a function, returning a function to be used as the | |
| 29 OnTextEnterPressed callback; this is typically how new entries should be | |
| 30 added to data | |
| 31 - 'values' field must be a function, returning the usual list of entries, PLUS | |
| 32 the callback used for 'get', e.g., | |
| 33 values = function() | |
| 34 local ret = build_real_dropdown_values() | |
| 35 ret[get_callback] = true -- assuming "function get_callback (widget, event, text)" | |
| 36 return ret | |
| 37 end | |
| 38 The callback will be immediately removed from the table, but is required to | |
| 39 be present to pass tests in the AceConfig source. | |
| 40 - 'set' receives the key of the dropdown table, but that entry will already be | |
| 41 removed by the time the 'set' function is called | |
| 42 | |
| 43 | |
| 44 EditBoxDropDown API | |
| 45 | |
| 46 :SetLabel(txt) | |
| 47 forwards to the editbox's SetLabel | |
| 48 | |
| 49 :SetText(txt) | |
| 50 forwards to the editbox's SetText | |
| 51 | |
| 52 :SetEditBoxTooltip(txt) | |
| 53 sets text for the tooltip shown when hovering over the editbox | |
| 54 no default | |
| 55 | |
| 56 :SetButtonTooltip(txt) | |
| 57 sets text for the tooltip shown when hovering over the dropdown button | |
| 58 default "Click on entries to remove them." | |
| 59 | |
| 60 :SetList(t) | |
| 61 T is a table to be shown in the dropdown list; the values will be displayed | |
| 62 in the dropdown | |
| 63 When entries are clicked, they will be removed from T. T is not copied, | |
| 64 the table is edited "live" before firing the callback below. | |
| 65 | |
| 66 | |
| 67 EditBoxDropDown Callbacks | |
| 68 | |
| 69 OnTextEnterPressed | |
| 70 same as the editbox's OnEnterPressed | |
| 71 | |
| 72 OnListItemClicked | |
| 73 similar to a Dropdown widget's OnValueChanged, the key and value from the | |
| 74 table given to :SetList are passed | |
| 75 | |
| 76 | |
| 77 farmbuyer | |
| 78 ]] | |
| 79 | |
| 80 local button_hover_text_default = "Click on entries to remove them." | |
| 81 local maps -- from actual editbox frame back to this widget | |
| 82 | |
| 83 | |
| 84 local function Menu_OnClick (button, userlist_key, widget) | |
| 85 local v = widget.list[userlist_key] | |
| 86 widget.list[userlist_key] = nil | |
| 87 widget.dropdown.is_on = nil | |
| 88 -- firing these off changes widget contents, must be done last :-( | |
| 89 widget:Fire("OnListItemClicked", userlist_key, v) | |
| 90 widget:Fire("OnValueChanged", userlist_key) | |
| 91 end | |
| 92 | |
| 93 local function BuildList (widget) | |
| 94 local ret = {} | |
| 95 if widget.list then for k,v in pairs(widget.list) do | |
| 96 table.insert (ret, { | |
| 97 text = tostring(v) or tostring(k), | |
| 98 func = Menu_OnClick, | |
| 99 arg1 = k, | |
| 100 arg2 = widget, | |
| 101 notCheckable = true, | |
| 102 }) | |
| 103 end end | |
| 104 return ret | |
| 105 end | |
| 106 | |
| 107 | |
| 108 local function ddEditBox_OnMouseEnter (editbox) | |
| 109 if editbox.tooltip_text then | |
| 110 GameTooltip:SetOwner(editbox.frame, "ANCHOR_RIGHT") | |
| 111 GameTooltip:SetText(editbox.tooltip_text, nil, nil, nil, nil, 1) | |
| 112 end | |
| 113 end | |
| 114 | |
| 115 local function ddEditBox_OnMouseLeave (editbox_or_button) | |
| 116 GameTooltip:Hide() | |
| 117 end | |
| 118 | |
| 119 local function ddEditBox_Clear (editboxframe) | |
| 120 editboxframe:SetText("") | |
| 121 end | |
| 122 | |
| 123 local function ddEditBox_Reset (editboxframe) -- :ClearFocus triggers this | |
| 124 editboxframe:SetText(maps[editboxframe].editbox_basetext or "") | |
| 125 end | |
| 126 | |
| 127 local function ddEditBox_OnEnterPressed (editbox, _, text) | |
| 128 editbox.obj:Fire("OnTextEnterPressed", text) | |
| 129 ddEditBox_Reset(editbox.editbox) | |
| 130 editbox.editbox:ClearFocus() -- cursor still blinking in there, one more time | |
| 131 end | |
| 132 | |
| 133 local function Button_OnClick (button) | |
| 134 local dd = button.obj.dropdown | |
| 135 -- Annoyingly, it's very tedious to find the correct nested frame to use | |
| 136 -- for :IsShown() here. We'll avoid it all by using our own flag. | |
| 137 if dd.is_on then | |
| 138 dd.is_on = nil | |
| 139 HideDropDownMenu(--[[level=]]1) -- EasyMenu always uses top/1 level | |
| 140 else | |
| 141 dd.is_on = true | |
| 142 local t = BuildList(button.obj) | |
| 143 EasyMenu (t, button.obj.dropdown, button.obj.frame, 0, 0, "MENU") | |
| 144 PlaySound("igMainMenuOptionCheckBoxOn") | |
| 145 end | |
| 146 end | |
| 147 | |
| 148 local function Button_OnEnter (button) | |
| 149 if button.tooltip_text then | |
| 150 GameTooltip:SetOwner(button, "ANCHOR_RIGHT") | |
| 151 GameTooltip:SetText(button.tooltip_text, nil, nil, nil, nil, 1) | |
| 152 end | |
| 153 end | |
| 154 | |
| 155 | |
| 156 local methods = { | |
| 157 ["OnAcquire"] = function (self) | |
| 158 self:SetHeight(20) | |
| 159 self:SetWidth(100) | |
| 160 self.button.tooltip_text = button_hover_text_default | |
| 161 self:SetList(nil) | |
| 162 self.editbox:DisableButton(true) | |
| 163 | |
| 164 maps = maps or {} | |
| 165 maps[self.editbox.editbox] = self | |
| 166 end, | |
| 167 | |
| 168 ["OnRelease"] = function (self) | |
| 169 self.frame:ClearAllPoints() | |
| 170 self.frame:Hide() | |
| 171 self.editbox.tooltip_text = nil | |
| 172 self.button.tooltip_text = nil | |
| 173 self:SetList(nil) | |
| 174 maps[self.editbox.editbox] = nil | |
| 175 end, | |
| 176 | |
| 177 ["SetParent"] = function (self, parent) | |
| 178 self.frame:SetParent(nil) | |
| 179 self.frame:SetParent(parent.content) | |
| 180 self.parent = parent | |
| 181 self.editbox:SetParent(parent) | |
| 182 end, | |
| 183 | |
| 184 ["SetText"] = function (self, text) | |
| 185 self.editbox_basetext = text | |
| 186 return self.editbox:SetText(text) | |
| 187 end, | |
| 188 | |
| 189 ["SetLabel"] = function (self, text) | |
| 190 return self.editbox:SetLabel(text) | |
| 191 end, | |
| 192 | |
| 193 ["SetDisabled"] = function (self, disabled) | |
| 194 self.editbox:SetDisabled(disabled) | |
| 195 if disabled then | |
| 196 self.button:Disable() | |
| 197 else | |
| 198 self.button:Enable() | |
| 199 end | |
| 200 end, | |
| 201 | |
| 202 ["SetList"] = function (self, list) | |
| 203 self.list = list | |
| 204 end, | |
| 205 | |
| 206 ["SetEditBoxTooltip"] = function (self, text) | |
| 207 self.editbox.tooltip_text = text | |
| 208 end, | |
| 209 | |
| 210 ["SetButtonTooltip"] = function (self, text) | |
| 211 self.button.tooltip_text = text | |
| 212 end, | |
| 213 } | |
| 214 | |
| 215 -- called with the 'name' entry | |
| 216 local function optcontrol_SetLabel (self, text) | |
| 217 local name, desc = ('\t'):split(text) | |
| 218 if desc then | |
| 219 self:SetEditBoxTooltip(desc) | |
| 220 end | |
| 221 self.editbox:SetLabel(name) | |
| 222 end | |
| 223 | |
| 224 local function optcontrol_SetValue (self, epcallback) | |
| 225 -- set the callback | |
| 226 self:SetCallback("OnTextEnterPressed", epcallback) | |
| 227 -- remove the fake entry from the values table | |
| 228 self.list[epcallback] = nil | |
| 229 end | |
| 230 | |
| 231 | |
| 232 local function Constructor(is_option_control) | |
| 233 local num = AceGUI:GetNextWidgetNum(Type) | |
| 234 | |
| 235 -- Its frame becomes our widget frame, else its frame is never shown. Gluing | |
| 236 -- them together seems a little evil, but it beats making this widget into a | |
| 237 -- formal containter. Inspired by new-style InteractiveLabel. | |
| 238 local editbox = AceGUI:Create("EditBox") | |
| 239 local frame = editbox.frame | |
| 240 editbox:SetHeight(20) | |
| 241 editbox:SetWidth(100) | |
| 242 frame:SetWidth(frame:GetWidth()+6) | |
| 243 editbox:SetCallback("OnEnter", ddEditBox_OnMouseEnter) | |
| 244 editbox:SetCallback("OnLeave", ddEditBox_OnMouseLeave) | |
| 245 editbox:SetCallback("OnEnterPressed", ddEditBox_OnEnterPressed) | |
| 246 editbox.editbox:SetScript("OnEditFocusGained", ddEditBox_Clear) | |
| 247 editbox.editbox:SetScript("OnEditFocusLost", ddEditBox_Reset) | |
| 248 --editbox.editbox:SetScript("OnEscapePressed", ddEditBox_Reset) | |
| 249 | |
| 250 local button = CreateFrame("Button", nil, frame) | |
| 251 button:SetHeight(20) | |
| 252 button:SetWidth(24) | |
| 253 button:SetPoint("LEFT", editbox.frame, "RIGHT", 0, 0) | |
| 254 button:SetNormalTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Up") | |
| 255 button:SetPushedTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Down") | |
| 256 button:SetDisabledTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Disabled") | |
| 257 button:SetHighlightTexture("Interface\\Buttons\\UI-Common-MouseHilight","ADD") | |
| 258 button:SetScript("OnClick", Button_OnClick) | |
| 259 button:SetScript("OnEnter", Button_OnEnter) | |
| 260 button:SetScript("OnLeave", ddEditBox_OnMouseLeave) | |
| 261 button.parent = frame | |
| 262 | |
| 263 local dropdown = CreateFrame("Frame", "AceGUI-3.0EditBoxDropDownMenu"..num, nil, "UIDropDownMenuTemplate") | |
| 264 dropdown:Hide() | |
| 265 | |
| 266 local widget = { | |
| 267 editbox = editbox, | |
| 268 button = button, | |
| 269 dropdown = dropdown, | |
| 270 frame = frame, | |
| 271 type = Type | |
| 272 } | |
| 273 for method, func in pairs(methods) do | |
| 274 widget[method] = func | |
| 275 end | |
| 276 editbox.obj, button.obj, dropdown.obj = widget, widget, widget | |
| 277 if is_option_control then | |
| 278 widget.is_option_control = true | |
| 279 widget.SetLabel = optcontrol_SetLabel | |
| 280 widget.SetValue = optcontrol_SetValue | |
| 281 end | |
| 282 | |
| 283 return AceGUI:RegisterAsWidget(widget) | |
| 284 end | |
| 285 | |
| 286 AceGUI:RegisterWidgetType (Type, Constructor, Version) | |
| 287 | |
| 288 AceGUI:RegisterWidgetType (Type.."OptionControl", function() return Constructor(true) end, Version) | |
| 289 |
