annotate AceGUIWidget-DoTimerEditBoxDropDown.lua @ 115:289c7667adab

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