Mercurial > wow > reaction
comparison modules/ReAction_ConfigUI/lib/Dewdrop-2.0/Dewdrop-2.0.lua @ 28:21bcaf8215ff
- converted to Ace3
- rearranged file layout
- configGUI menus not working right now
| author | Flick <flickerstreak@gmail.com> |
|---|---|
| date | Mon, 17 Mar 2008 18:24:53 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 27:f1e838841ce1 | 28:21bcaf8215ff |
|---|---|
| 1 --[[ | |
| 2 Name: Dewdrop-2.0 | |
| 3 Revision: $Rev: 48630 $ | |
| 4 Author(s): ckknight (ckknight@gmail.com) | |
| 5 Website: http://ckknight.wowinterface.com/ | |
| 6 Documentation: http://wiki.wowace.com/index.php/Dewdrop-2.0 | |
| 7 SVN: http://svn.wowace.com/root/trunk/DewdropLib/Dewdrop-2.0 | |
| 8 Description: A library to provide a clean dropdown menu interface. | |
| 9 Dependencies: AceLibrary | |
| 10 License: LGPL v2.1 | |
| 11 ]] | |
| 12 | |
| 13 local MAJOR_VERSION = "Dewdrop-2.0" | |
| 14 local MINOR_VERSION = "$Revision: 48630 $" | |
| 15 | |
| 16 if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end | |
| 17 if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end | |
| 18 | |
| 19 local Dewdrop = {} | |
| 20 | |
| 21 local SharedMedia | |
| 22 | |
| 23 local CLOSE = "Close" | |
| 24 local CLOSE_DESC = "Close the menu." | |
| 25 local VALIDATION_ERROR = "Validation error." | |
| 26 local USAGE_TOOLTIP = "Usage: %s." | |
| 27 local RANGE_TOOLTIP = "Note that you can scroll your mouse wheel while over the slider to step by one." | |
| 28 local RESET_KEYBINDING_DESC = "Hit escape to clear the keybinding." | |
| 29 local KEY_BUTTON1 = "Left Mouse" | |
| 30 local KEY_BUTTON2 = "Right Mouse" | |
| 31 local DISABLED = "Disabled" | |
| 32 local DEFAULT_CONFIRM_MESSAGE = "Are you sure you want to perform `%s'?" | |
| 33 | |
| 34 if GetLocale() == "deDE" then | |
| 35 CLOSE = "Schlie\195\159en" | |
| 36 CLOSE_DESC = "Men\195\188 schlie\195\159en." | |
| 37 VALIDATION_ERROR = "Validierungsfehler." | |
| 38 USAGE_TOOLTIP = "Benutzung: %s." | |
| 39 RANGE_TOOLTIP = "Beachte das du mit dem Mausrad scrollen kannst solange du \195\188ber dem Schieberegler bist, um 10er Spr\195\188nge zu machen." | |
| 40 RESET_KEYBINDING_DESC = "Escape dr\195\188cken, um die Tastenbelegung zu l\195\182schen." | |
| 41 KEY_BUTTON1 = "Linke Maustaste" | |
| 42 KEY_BUTTON2 = "Rechte Maustaste" | |
| 43 DISABLED = "Deaktiviert" | |
| 44 DEFAULT_CONFIRM_MESSAGE = "Bist du sicher das du `%s' machen willst?" | |
| 45 elseif GetLocale() == "koKR" then | |
| 46 CLOSE = "닫기" | |
| 47 CLOSE_DESC = "메뉴를 닫습니다." | |
| 48 VALIDATION_ERROR = "오류 확인." | |
| 49 USAGE_TOOLTIP = "사용법: %s." | |
| 50 RANGE_TOOLTIP = "알림 : 슬라이더 위에서 마우스 휠을 사용하면 한단계씩 조절할 수 있습니다." | |
| 51 RESET_KEYBINDING_DESC = "단축키를 해제하려면 ESC키를 누르세요." | |
| 52 KEY_BUTTON1 = "왼쪽 마우스" | |
| 53 KEY_BUTTON2 = "오른쪽 마우스" | |
| 54 DISABLED = "비활성화됨" | |
| 55 DEFAULT_CONFIRM_MESSAGE = "정말로 `%s' 실행을 하시겠습니까 ?" | |
| 56 elseif GetLocale() == "frFR" then | |
| 57 CLOSE = "Fermer" | |
| 58 CLOSE_DESC = "Ferme le menu." | |
| 59 VALIDATION_ERROR = "Erreur de validation." | |
| 60 USAGE_TOOLTIP = "Utilisation : %s." | |
| 61 RANGE_TOOLTIP = "Vous pouvez aussi utiliser la molette de la souris pour pour modifier progressivement." | |
| 62 RESET_KEYBINDING_DESC = "Appuyez sur la touche Echappement pour effacer le raccourci." | |
| 63 KEY_BUTTON1 = "Clic gauche" | |
| 64 KEY_BUTTON2 = "Clic droit" | |
| 65 DISABLED = "D\195\169sactiv\195\169" | |
| 66 DEFAULT_CONFIRM_MESSAGE = "\195\138tes-vous s\195\187r de vouloir effectuer '%s' ?" | |
| 67 elseif GetLocale() == "esES" then | |
| 68 CLOSE = "Cerrar" | |
| 69 CLOSE_DESC = "Cierra el menú." | |
| 70 VALIDATION_ERROR = "Error de validación." | |
| 71 USAGE_TOOLTIP = "Uso: %s." | |
| 72 RANGE_TOOLTIP = "Puedes desplazarte verticalmente con la rueda del ratón sobre el desplazador." | |
| 73 RESET_KEYBINDING_DESC = "Pulsa Escape para borrar la asignación de tecla." | |
| 74 KEY_BUTTON1 = "Clic Izquierdo" | |
| 75 KEY_BUTTON2 = "Clic Derecho" | |
| 76 DISABLED = "Desactivado" | |
| 77 DEFAULT_CONFIRM_MESSAGE = "¿Estás seguro de querer realizar `%s'?" | |
| 78 elseif GetLocale() == "zhTW" then | |
| 79 CLOSE = "關閉" | |
| 80 CLOSE_DESC = "關閉選單。" | |
| 81 VALIDATION_ERROR = "驗證錯誤。" | |
| 82 USAGE_TOOLTIP = "用法: %s。" | |
| 83 RANGE_TOOLTIP = "你可以在捲動條上使用滑鼠滾輪來捲動。" | |
| 84 RESET_KEYBINDING_DESC = "按Esc鍵清除快捷鍵。" | |
| 85 KEY_BUTTON1 = "滑鼠左鍵" | |
| 86 KEY_BUTTON2 = "滑鼠右鍵" | |
| 87 DISABLED = "停用" | |
| 88 DEFAULT_CONFIRM_MESSAGE = "是否執行「%s」?" | |
| 89 elseif GetLocale() == "zhCN" then | |
| 90 CLOSE = "关闭" | |
| 91 CLOSE_DESC = "关闭菜单" | |
| 92 VALIDATION_ERROR = "验证错误." | |
| 93 USAGE_TOOLTIP = "用法: %s." | |
| 94 RANGE_TOOLTIP = "你可以在滚动条上使用鼠标滚轮来翻页." | |
| 95 RESET_KEYBINDING_DESC = "按ESC键清除按键绑定" | |
| 96 KEY_BUTTON1 = "鼠标左键" | |
| 97 KEY_BUTTON2 = "鼠标右键" | |
| 98 DISABLED = "禁用" | |
| 99 DEFAULT_CONFIRM_MESSAGE = "是否执行'%s'?" | |
| 100 end | |
| 101 | |
| 102 Dewdrop.KEY_BUTTON1 = KEY_BUTTON1 | |
| 103 Dewdrop.KEY_BUTTON2 = KEY_BUTTON2 | |
| 104 | |
| 105 local function new(...) | |
| 106 local t = {} | |
| 107 for i = 1, select('#', ...), 2 do | |
| 108 local k = select(i, ...) | |
| 109 if k then | |
| 110 t[k] = select(i+1, ...) | |
| 111 else | |
| 112 break | |
| 113 end | |
| 114 end | |
| 115 return t | |
| 116 end | |
| 117 | |
| 118 local tmp | |
| 119 do | |
| 120 local t = {} | |
| 121 function tmp(...) | |
| 122 for k in pairs(t) do | |
| 123 t[k] = nil | |
| 124 end | |
| 125 for i = 1, select('#', ...), 2 do | |
| 126 local k = select(i, ...) | |
| 127 if k then | |
| 128 t[k] = select(i+1, ...) | |
| 129 else | |
| 130 break | |
| 131 end | |
| 132 end | |
| 133 return t | |
| 134 end | |
| 135 end | |
| 136 local tmp2 | |
| 137 do | |
| 138 local t = {} | |
| 139 function tmp2(...) | |
| 140 for k in pairs(t) do | |
| 141 t[k] = nil | |
| 142 end | |
| 143 for i = 1, select('#', ...), 2 do | |
| 144 local k = select(i, ...) | |
| 145 if k then | |
| 146 t[k] = select(i+1, ...) | |
| 147 else | |
| 148 break | |
| 149 end | |
| 150 end | |
| 151 return t | |
| 152 end | |
| 153 end | |
| 154 local levels | |
| 155 local buttons | |
| 156 | |
| 157 | |
| 158 -- Secure frame handling: | |
| 159 -- Rather than using secure buttons in the menu (has problems), we have one | |
| 160 -- master secureframe that we pop onto menu items on mouseover. This requires | |
| 161 -- some dark magic with OnLeave etc, but it's not too bad. | |
| 162 | |
| 163 local secureFrame = CreateFrame("Button", nil, nil, "SecureActionButtonTemplate") | |
| 164 secureFrame:Hide() | |
| 165 | |
| 166 local function secureFrame_Show(self) | |
| 167 local owner = self.owner | |
| 168 | |
| 169 if self.secure then -- Leftovers from previos owner, clean up! ("Shouldn't" happen but does..) | |
| 170 for k,v in pairs(self.secure) do | |
| 171 self:SetAttribute(k, nil) | |
| 172 end | |
| 173 end | |
| 174 self.secure = owner.secure; -- Grab hold of new secure data | |
| 175 | |
| 176 local scale = owner:GetEffectiveScale() | |
| 177 | |
| 178 self:SetPoint("TOPLEFT", nil, "BOTTOMLEFT", owner:GetLeft() * scale, owner:GetTop() * scale) | |
| 179 self:SetPoint("BOTTOMRIGHT", nil, "BOTTOMLEFT", owner:GetRight() * scale, owner:GetBottom() * scale) | |
| 180 self:EnableMouse(true) | |
| 181 for k,v in pairs(self.secure) do | |
| 182 self:SetAttribute(k, v) | |
| 183 end | |
| 184 | |
| 185 secureFrame:SetFrameStrata(owner:GetFrameStrata()) | |
| 186 secureFrame:SetFrameLevel(owner:GetFrameLevel()+1) | |
| 187 | |
| 188 self:Show() | |
| 189 end | |
| 190 | |
| 191 local function secureFrame_Hide(self) | |
| 192 self:Hide() | |
| 193 if self.secure then | |
| 194 for k,v in pairs(self.secure) do | |
| 195 self:SetAttribute(k, nil) | |
| 196 end | |
| 197 end | |
| 198 self.secure = nil | |
| 199 end | |
| 200 | |
| 201 secureFrame:SetScript("OnEvent", | |
| 202 function() | |
| 203 if event=="PLAYER_REGEN_ENABLED" then | |
| 204 this.combat = false | |
| 205 if not this:IsShown() and this.owner then | |
| 206 secureFrame_Show(this) | |
| 207 end | |
| 208 elseif event=="PLAYER_REGEN_DISABLED" then | |
| 209 this.combat = true | |
| 210 if this:IsShown() then | |
| 211 secureFrame_Hide(this) | |
| 212 end | |
| 213 end | |
| 214 end | |
| 215 ) | |
| 216 secureFrame:RegisterEvent("PLAYER_REGEN_ENABLED") | |
| 217 secureFrame:RegisterEvent("PLAYER_REGEN_DISABLED") | |
| 218 | |
| 219 secureFrame:SetScript("OnLeave", | |
| 220 function() | |
| 221 local owner=this.owner | |
| 222 this:Deactivate() | |
| 223 owner:GetScript("OnLeave")() | |
| 224 end | |
| 225 ) | |
| 226 | |
| 227 secureFrame:HookScript("OnClick", | |
| 228 function() | |
| 229 local realthis = this | |
| 230 this = this.owner | |
| 231 this:GetScript("OnClick")() | |
| 232 end | |
| 233 ) | |
| 234 | |
| 235 function secureFrame:IsOwnedBy(frame) | |
| 236 return self.owner == frame | |
| 237 end | |
| 238 | |
| 239 function secureFrame:Activate(owner) | |
| 240 if self.owner then -- "Shouldn't" happen but apparently it does and I cba to troubleshoot... | |
| 241 if not self.combat then | |
| 242 secureFrame_Hide(self) | |
| 243 end | |
| 244 end | |
| 245 self.owner = owner | |
| 246 if not self.combat then | |
| 247 secureFrame_Show(self) | |
| 248 end | |
| 249 end | |
| 250 | |
| 251 function secureFrame:Deactivate() | |
| 252 if not self.combat then | |
| 253 secureFrame_Hide(self) | |
| 254 end | |
| 255 self.owner = nil | |
| 256 end | |
| 257 | |
| 258 -- END secure frame utilities | |
| 259 | |
| 260 | |
| 261 -- Underline on mouseover - use a single global underline that we move around, no point in creating lots of copies | |
| 262 local underlineFrame = CreateFrame("Frame", nil) | |
| 263 underlineFrame.tx = underlineFrame:CreateTexture() | |
| 264 underlineFrame.tx:SetTexture(1,1,0.5,0.75) | |
| 265 underlineFrame:SetScript("OnHide", function(this) this:Hide(); end) | |
| 266 underlineFrame:SetScript("OnShow", function(this) -- change sizing on the fly to catch runtime uiscale changes | |
| 267 underlineFrame.tx:SetPoint("TOPLEFT", -1, -2/this:GetEffectiveScale()) | |
| 268 underlineFrame.tx:SetPoint("RIGHT", 1,0) | |
| 269 underlineFrame.tx:SetHeight(0.6 / this:GetEffectiveScale()); | |
| 270 end) | |
| 271 underlineFrame:SetHeight(1) | |
| 272 | |
| 273 -- END underline on mouseover | |
| 274 | |
| 275 | |
| 276 local function GetScaledCursorPosition() | |
| 277 local x, y = GetCursorPosition() | |
| 278 local scale = UIParent:GetEffectiveScale() | |
| 279 return x / scale, y / scale | |
| 280 end | |
| 281 | |
| 282 local function StartCounting(self, level) | |
| 283 for i = level, 1, -1 do | |
| 284 if levels[i] then | |
| 285 levels[i].count = 3 | |
| 286 end | |
| 287 end | |
| 288 end | |
| 289 | |
| 290 local function StopCounting(self, level) | |
| 291 for i = level, 1, -1 do | |
| 292 if levels[i] then | |
| 293 levels[i].count = nil | |
| 294 end | |
| 295 end | |
| 296 end | |
| 297 | |
| 298 local function OnUpdate(self, elapsed) | |
| 299 for _,level in ipairs(levels) do | |
| 300 local count = level.count | |
| 301 if count then | |
| 302 count = count - elapsed | |
| 303 if count < 0 then | |
| 304 level.count = nil | |
| 305 self:Close(level.num) | |
| 306 else | |
| 307 level.count = count | |
| 308 end | |
| 309 end | |
| 310 end | |
| 311 end | |
| 312 | |
| 313 local function CheckDualMonitor(self, frame) | |
| 314 local ratio = GetScreenWidth() / GetScreenHeight() | |
| 315 if ratio >= 2.4 and frame:GetRight() > GetScreenWidth() / 2 and frame:GetLeft() < GetScreenWidth() / 2 then | |
| 316 local offsetx | |
| 317 if GetCursorPosition() / GetScreenHeight() * 768 < GetScreenWidth() / 2 then | |
| 318 offsetx = GetScreenWidth() / 2 - frame:GetRight() | |
| 319 else | |
| 320 offsetx = GetScreenWidth() / 2 - frame:GetLeft() | |
| 321 end | |
| 322 local point, parent, relativePoint, x, y = frame:GetPoint(1) | |
| 323 frame:SetPoint(point, parent, relativePoint, (x or 0) + offsetx, y or 0) | |
| 324 end | |
| 325 end | |
| 326 | |
| 327 local function CheckSize(self, level) | |
| 328 if not level.buttons then | |
| 329 return | |
| 330 end | |
| 331 local height = 20 | |
| 332 for _, button in ipairs(level.buttons) do | |
| 333 height = height + button:GetHeight() | |
| 334 end | |
| 335 level:SetHeight(height) | |
| 336 local width = 160 | |
| 337 for _, button in ipairs(level.buttons) do | |
| 338 local extra = 1 | |
| 339 if button.hasArrow or button.hasColorSwatch then | |
| 340 extra = extra + 16 | |
| 341 end | |
| 342 if not button.notCheckable then | |
| 343 extra = extra + 24 | |
| 344 end | |
| 345 button.text:SetFont(STANDARD_TEXT_FONT, button.textHeight) | |
| 346 if button.text:GetWidth() + extra > width then | |
| 347 width = button.text:GetWidth() + extra | |
| 348 end | |
| 349 end | |
| 350 level:SetWidth(width + 20) | |
| 351 if level:GetLeft() and level:GetRight() and level:GetTop() and level:GetBottom() and (level:GetLeft() < 0 or level:GetRight() > GetScreenWidth() or level:GetTop() > GetScreenHeight() or level:GetBottom() < 0) then | |
| 352 level:ClearAllPoints() | |
| 353 local parent = level.parent or level:GetParent() | |
| 354 if type(parent) ~= "table" then | |
| 355 parent = UIParent | |
| 356 end | |
| 357 if level.lastDirection == "RIGHT" then | |
| 358 if level.lastVDirection == "DOWN" then | |
| 359 level:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) | |
| 360 else | |
| 361 level:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) | |
| 362 end | |
| 363 else | |
| 364 if level.lastVDirection == "DOWN" then | |
| 365 level:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) | |
| 366 else | |
| 367 level:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) | |
| 368 end | |
| 369 end | |
| 370 end | |
| 371 local dirty = false | |
| 372 if not level:GetRight() then | |
| 373 self:Close() | |
| 374 return | |
| 375 end | |
| 376 if level:GetRight() > GetScreenWidth() and level.lastDirection == "RIGHT" then | |
| 377 level.lastDirection = "LEFT" | |
| 378 dirty = true | |
| 379 elseif level:GetLeft() < 0 and level.lastDirection == "LEFT" then | |
| 380 level.lastDirection = "RIGHT" | |
| 381 dirty = true | |
| 382 end | |
| 383 if level:GetTop() > GetScreenHeight() and level.lastVDirection == "UP" then | |
| 384 level.lastVDirection = "DOWN" | |
| 385 dirty = true | |
| 386 elseif level:GetBottom() < 0 and level.lastVDirection == "DOWN" then | |
| 387 level.lastVDirection = "UP" | |
| 388 dirty = true | |
| 389 end | |
| 390 if dirty then | |
| 391 level:ClearAllPoints() | |
| 392 local parent = level.parent or level:GetParent() | |
| 393 if type(parent) ~= "table" then | |
| 394 parent = UIParent | |
| 395 end | |
| 396 if level.lastDirection == "RIGHT" then | |
| 397 if level.lastVDirection == "DOWN" then | |
| 398 level:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) | |
| 399 else | |
| 400 level:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) | |
| 401 end | |
| 402 else | |
| 403 if level.lastVDirection == "DOWN" then | |
| 404 level:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) | |
| 405 else | |
| 406 level:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) | |
| 407 end | |
| 408 end | |
| 409 end | |
| 410 if level:GetTop() > GetScreenHeight() then | |
| 411 local top = level:GetTop() | |
| 412 local point, parent, relativePoint, x, y = level:GetPoint(1) | |
| 413 level:ClearAllPoints() | |
| 414 level:SetPoint(point, parent, relativePoint, x or 0, (y or 0) + GetScreenHeight() - top) | |
| 415 elseif level:GetBottom() < 0 then | |
| 416 local bottom = level:GetBottom() | |
| 417 local point, parent, relativePoint, x, y = level:GetPoint(1) | |
| 418 level:ClearAllPoints() | |
| 419 level:SetPoint(point, parent, relativePoint, x or 0, (y or 0) - bottom) | |
| 420 end | |
| 421 CheckDualMonitor(self, level) | |
| 422 if mod(level.num, 5) == 0 then | |
| 423 local left, bottom = level:GetLeft(), level:GetBottom() | |
| 424 level:ClearAllPoints() | |
| 425 level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) | |
| 426 end | |
| 427 end | |
| 428 | |
| 429 local Open | |
| 430 local OpenSlider | |
| 431 local OpenEditBox | |
| 432 local Refresh | |
| 433 local Clear | |
| 434 local function ReleaseButton(self, level, index) | |
| 435 if not level.buttons then | |
| 436 return | |
| 437 end | |
| 438 if not level.buttons[index] then | |
| 439 return | |
| 440 end | |
| 441 local button = level.buttons[index] | |
| 442 button:Hide() | |
| 443 if button.highlight then | |
| 444 button.highlight:Hide() | |
| 445 end | |
| 446 -- button.arrow:SetVertexColor(1, 1, 1) | |
| 447 -- button.arrow:SetHeight(16) | |
| 448 -- button.arrow:SetWidth(16) | |
| 449 table.remove(level.buttons, index) | |
| 450 table.insert(buttons, button) | |
| 451 for k in pairs(button) do | |
| 452 if k ~= 0 and k ~= "text" and k ~= "check" and k ~= "arrow" and k ~= "colorSwatch" and k ~= "highlight" and k ~= "radioHighlight" then | |
| 453 button[k] = nil | |
| 454 end | |
| 455 end | |
| 456 return true | |
| 457 end | |
| 458 | |
| 459 local function Scroll(self, level, down) | |
| 460 if down then | |
| 461 if level:GetBottom() < 0 then | |
| 462 local point, parent, relativePoint, x, y = level:GetPoint(1) | |
| 463 level:SetPoint(point, parent, relativePoint, x, y + 50) | |
| 464 if level:GetBottom() > 0 then | |
| 465 level:SetPoint(point, parent, relativePoint, x, y + 50 - level:GetBottom()) | |
| 466 end | |
| 467 end | |
| 468 else | |
| 469 if level:GetTop() > GetScreenHeight() then | |
| 470 local point, parent, relativePoint, x, y = level:GetPoint(1) | |
| 471 level:SetPoint(point, parent, relativePoint, x, y - 50) | |
| 472 if level:GetTop() < GetScreenHeight() then | |
| 473 level:SetPoint(point, parent, relativePoint, x, y - 50 + GetScreenHeight() - level:GetTop()) | |
| 474 end | |
| 475 end | |
| 476 end | |
| 477 end | |
| 478 | |
| 479 local function getArgs(t, str, num, ...) | |
| 480 local x = t[str .. num] | |
| 481 if x == nil then | |
| 482 return ... | |
| 483 else | |
| 484 return x, getArgs(t, str, num + 1, ...) | |
| 485 end | |
| 486 end | |
| 487 | |
| 488 local sliderFrame | |
| 489 local editBoxFrame | |
| 490 | |
| 491 local normalFont | |
| 492 local lastSetFont | |
| 493 local justSetFont = false | |
| 494 local regionTmp = {} | |
| 495 local function fillRegionTmp(...) | |
| 496 for i = 1, select('#', ...) do | |
| 497 regionTmp[i] = select(i, ...) | |
| 498 end | |
| 499 end | |
| 500 | |
| 501 local function showGameTooltip(this) | |
| 502 if this.tooltipTitle or this.tooltipText then | |
| 503 GameTooltip_SetDefaultAnchor(GameTooltip, this) | |
| 504 local disabled = not this.isTitle and this.disabled | |
| 505 local font | |
| 506 if this.tooltipTitle then | |
| 507 if SharedMedia and SharedMedia:IsValid("font", this.tooltipTitle) then | |
| 508 font = SharedMedia:Fetch("font", this.tooltipTitle) | |
| 509 end | |
| 510 if disabled then | |
| 511 GameTooltip:SetText(this.tooltipTitle, 0.5, 0.5, 0.5, 1) | |
| 512 else | |
| 513 GameTooltip:SetText(this.tooltipTitle, 1, 1, 1, 1) | |
| 514 end | |
| 515 if this.tooltipText then | |
| 516 if not font and SharedMedia and SharedMedia:IsValid("font", this.tooltipText) then | |
| 517 font = SharedMedia:Fetch("font", this.tooltipText) | |
| 518 end | |
| 519 if disabled then | |
| 520 GameTooltip:AddLine(this.tooltipText, (NORMAL_FONT_COLOR.r + 0.5) / 2, (NORMAL_FONT_COLOR.g + 0.5) / 2, (NORMAL_FONT_COLOR.b + 0.5) / 2, 1) | |
| 521 else | |
| 522 GameTooltip:AddLine(this.tooltipText, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) | |
| 523 end | |
| 524 end | |
| 525 else | |
| 526 if SharedMedia and SharedMedia:IsValid("font", this.tooltipText) then | |
| 527 font = SharedMedia:Fetch("font", this.tooltipText) | |
| 528 end | |
| 529 if disabled then | |
| 530 GameTooltip:SetText(this.tooltipText, 0.5, 0.5, 0.5, 1) | |
| 531 else | |
| 532 GameTooltip:SetText(this.tooltipText, 1, 1, 1, 1) | |
| 533 end | |
| 534 end | |
| 535 if font then | |
| 536 fillRegionTmp(GameTooltip:GetRegions()) | |
| 537 lastSetFont = font | |
| 538 justSetFont = true | |
| 539 for i,v in ipairs(regionTmp) do | |
| 540 if v.SetFont then | |
| 541 local norm,size,outline = v:GetFont() | |
| 542 v:SetFont(font, size, outline) | |
| 543 if not normalFont then | |
| 544 normalFont = norm | |
| 545 end | |
| 546 end | |
| 547 regionTmp[i] = nil | |
| 548 end | |
| 549 elseif not normalFont then | |
| 550 fillRegionTmp(GameTooltip:GetRegions()) | |
| 551 for i,v in ipairs(regionTmp) do | |
| 552 if v.GetFont and not normalFont then | |
| 553 normalFont = v:GetFont() | |
| 554 end | |
| 555 regionTmp[i] = nil | |
| 556 end | |
| 557 end | |
| 558 GameTooltip:Show() | |
| 559 end | |
| 560 if this.tooltipFunc then | |
| 561 GameTooltip:SetOwner(this, "ANCHOR_NONE") | |
| 562 GameTooltip:SetPoint("TOPLEFT", this, "TOPRIGHT", 5, 0) | |
| 563 this.tooltipFunc(getArgs(this, 'tooltipArg', 1)) | |
| 564 GameTooltip:Show() | |
| 565 end | |
| 566 end | |
| 567 | |
| 568 local tmpt = setmetatable({}, {mode='v'}) | |
| 569 local numButtons = 0 | |
| 570 local function AcquireButton(self, level) | |
| 571 if not levels[level] then | |
| 572 return | |
| 573 end | |
| 574 level = levels[level] | |
| 575 if not level.buttons then | |
| 576 level.buttons = {} | |
| 577 end | |
| 578 local button | |
| 579 if #buttons == 0 then | |
| 580 numButtons = numButtons + 1 | |
| 581 button = CreateFrame("Button", "Dewdrop20Button" .. numButtons, nil) | |
| 582 button:SetFrameStrata("FULLSCREEN_DIALOG") | |
| 583 button:SetHeight(16) | |
| 584 local highlight = button:CreateTexture(nil, "BACKGROUND") | |
| 585 highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight") | |
| 586 button.highlight = highlight | |
| 587 highlight:SetBlendMode("ADD") | |
| 588 highlight:SetAllPoints(button) | |
| 589 highlight:Hide() | |
| 590 local check = button:CreateTexture(nil, "ARTWORK") | |
| 591 button.check = check | |
| 592 check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") | |
| 593 check:SetPoint("CENTER", button, "LEFT", 12, 0) | |
| 594 check:SetWidth(24) | |
| 595 check:SetHeight(24) | |
| 596 local radioHighlight = button:CreateTexture(nil, "ARTWORK") | |
| 597 button.radioHighlight = radioHighlight | |
| 598 radioHighlight:SetTexture("Interface\\Buttons\\UI-RadioButton") | |
| 599 radioHighlight:SetAllPoints(check) | |
| 600 radioHighlight:SetBlendMode("ADD") | |
| 601 radioHighlight:SetTexCoord(0.5, 0.75, 0, 1) | |
| 602 radioHighlight:Hide() | |
| 603 button:SetScript("OnEnter", function() | |
| 604 if (sliderFrame and sliderFrame:IsShown() and sliderFrame.mouseDown and sliderFrame.level == this.level.num + 1) or (editBoxFrame and editBoxFrame:IsShown() and editBoxFrame.mouseDown and editBoxFrame.level == this.level.num + 1) then | |
| 605 for i = 1, this.level.num do | |
| 606 Refresh(self, levels[i]) | |
| 607 end | |
| 608 return | |
| 609 end | |
| 610 self:Close(this.level.num + 1) | |
| 611 if not this.disabled then | |
| 612 if this.secure then | |
| 613 secureFrame:Activate(this) | |
| 614 elseif this.hasSlider then | |
| 615 OpenSlider(self, this) | |
| 616 elseif this.hasEditBox then | |
| 617 OpenEditBox(self, this) | |
| 618 elseif this.hasArrow then | |
| 619 Open(self, this, nil, this.level.num + 1, this.value) | |
| 620 end | |
| 621 end | |
| 622 if not this.level then -- button reclaimed | |
| 623 return | |
| 624 end | |
| 625 StopCounting(self, this.level.num + 1) | |
| 626 if not this.disabled then | |
| 627 highlight:Show() | |
| 628 if this.isRadio then | |
| 629 button.radioHighlight:Show() | |
| 630 end | |
| 631 if this.mouseoverUnderline then | |
| 632 underlineFrame:SetParent(this) | |
| 633 underlineFrame:SetPoint("BOTTOMLEFT",this.text,0,0) | |
| 634 underlineFrame:SetWidth(this.text:GetWidth()) | |
| 635 underlineFrame:Show() | |
| 636 end | |
| 637 end | |
| 638 showGameTooltip(this) | |
| 639 end) | |
| 640 button:SetScript("OnHide", function() | |
| 641 if this.secure and secureFrame:IsOwnedBy(this) then | |
| 642 secureFrame:Deactivate() | |
| 643 end | |
| 644 end) | |
| 645 button:SetScript("OnLeave", function() | |
| 646 if this.secure and secureFrame:IsShown() then | |
| 647 return; -- it's ok, we didn't actually mouse out of the button, only onto the secure frame on top of it | |
| 648 end | |
| 649 underlineFrame:Hide() | |
| 650 if not this.selected then | |
| 651 highlight:Hide() | |
| 652 end | |
| 653 button.radioHighlight:Hide() | |
| 654 if this.level then | |
| 655 StartCounting(self, this.level.num) | |
| 656 end | |
| 657 GameTooltip:Hide() | |
| 658 end) | |
| 659 local first = true | |
| 660 button:SetScript("OnClick", function() | |
| 661 if not this.disabled then | |
| 662 if this.hasColorSwatch then | |
| 663 local func = button.colorFunc | |
| 664 local hasOpacity = this.hasOpacity | |
| 665 local this = this | |
| 666 for k in pairs(tmpt) do | |
| 667 tmpt[k] = nil | |
| 668 end | |
| 669 for i = 1, 1000 do | |
| 670 local x = this['colorArg'..i] | |
| 671 if x == nil then | |
| 672 break | |
| 673 else | |
| 674 tmpt[i] = x | |
| 675 end | |
| 676 end | |
| 677 ColorPickerFrame.func = function() | |
| 678 if func then | |
| 679 local r,g,b = ColorPickerFrame:GetColorRGB() | |
| 680 local a = hasOpacity and 1 - OpacitySliderFrame:GetValue() or nil | |
| 681 local n = #tmpt | |
| 682 tmpt[n+1] = r | |
| 683 tmpt[n+2] = g | |
| 684 tmpt[n+3] = b | |
| 685 tmpt[n+4] = a | |
| 686 func(unpack(tmpt)) | |
| 687 tmpt[n+1] = nil | |
| 688 tmpt[n+2] = nil | |
| 689 tmpt[n+3] = nil | |
| 690 tmpt[n+4] = nil | |
| 691 end | |
| 692 end | |
| 693 ColorPickerFrame.hasOpacity = this.hasOpacity | |
| 694 ColorPickerFrame.opacityFunc = ColorPickerFrame.func | |
| 695 ColorPickerFrame.opacity = 1 - this.opacity | |
| 696 ColorPickerFrame:SetColorRGB(this.r, this.g, this.b) | |
| 697 local r, g, b, a = this.r, this.g, this.b, this.opacity | |
| 698 ColorPickerFrame.cancelFunc = function() | |
| 699 if func then | |
| 700 local n = #tmpt | |
| 701 tmpt[n+1] = r | |
| 702 tmpt[n+2] = g | |
| 703 tmpt[n+3] = b | |
| 704 tmpt[n+4] = a | |
| 705 func(unpack(tmpt)) | |
| 706 for i = 1, n+4 do | |
| 707 tmpt[i] = nil | |
| 708 end | |
| 709 end | |
| 710 end | |
| 711 self:Close(1) | |
| 712 ShowUIPanel(ColorPickerFrame) | |
| 713 elseif this.func then | |
| 714 local level = this.level | |
| 715 if type(this.func) == "string" then | |
| 716 if type(this.arg1[this.func]) ~= "function" then | |
| 717 self:error("Cannot call method %q", this.func) | |
| 718 end | |
| 719 this.arg1[this.func](this.arg1, getArgs(this, 'arg', 2)) | |
| 720 else | |
| 721 this.func(getArgs(this, 'arg', 1)) | |
| 722 end | |
| 723 if this.closeWhenClicked then | |
| 724 self:Close() | |
| 725 elseif level:IsShown() then | |
| 726 for i = 1, level.num do | |
| 727 Refresh(self, levels[i]) | |
| 728 end | |
| 729 local value = levels[level.num].value | |
| 730 for i = level.num-1, 1, -1 do | |
| 731 local level = levels[i] | |
| 732 local good = false | |
| 733 for _,button in ipairs(level.buttons) do | |
| 734 if button.value == value then | |
| 735 good = true | |
| 736 break | |
| 737 end | |
| 738 end | |
| 739 if not good then | |
| 740 Dewdrop:Close(i+1) | |
| 741 end | |
| 742 value = levels[i].value | |
| 743 end | |
| 744 end | |
| 745 elseif this.closeWhenClicked then | |
| 746 self:Close() | |
| 747 end | |
| 748 end | |
| 749 end) | |
| 750 local text = button:CreateFontString(nil, "ARTWORK") | |
| 751 button.text = text | |
| 752 text:SetFontObject(GameFontHighlightSmall) | |
| 753 button.text:SetFont(STANDARD_TEXT_FONT, UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT) | |
| 754 button:SetScript("OnMouseDown", function() | |
| 755 if not this.disabled and (this.func or this.colorFunc or this.closeWhenClicked) then | |
| 756 text:SetPoint("LEFT", button, "LEFT", this.notCheckable and 1 or 25, -1) | |
| 757 end | |
| 758 end) | |
| 759 button:SetScript("OnMouseUp", function() | |
| 760 if not this.disabled and (this.func or this.colorFunc or this.closeWhenClicked) then | |
| 761 text:SetPoint("LEFT", button, "LEFT", this.notCheckable and 0 or 24, 0) | |
| 762 end | |
| 763 end) | |
| 764 local arrow = button:CreateTexture(nil, "ARTWORK") | |
| 765 button.arrow = arrow | |
| 766 arrow:SetPoint("LEFT", button, "RIGHT", -16, 0) | |
| 767 arrow:SetWidth(16) | |
| 768 arrow:SetHeight(16) | |
| 769 arrow:SetTexture("Interface\\ChatFrame\\ChatFrameExpandArrow") | |
| 770 local colorSwatch = button:CreateTexture(nil, "ARTWORK") | |
| 771 button.colorSwatch = colorSwatch | |
| 772 colorSwatch:SetWidth(20) | |
| 773 colorSwatch:SetHeight(20) | |
| 774 colorSwatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch") | |
| 775 local texture = button:CreateTexture(nil, "OVERLAY") | |
| 776 colorSwatch.texture = texture | |
| 777 texture:SetTexture("Interface\\Buttons\\WHITE8X8") | |
| 778 texture:SetWidth(11.5) | |
| 779 texture:SetHeight(11.5) | |
| 780 texture:Show() | |
| 781 texture:SetPoint("CENTER", colorSwatch, "CENTER") | |
| 782 colorSwatch:SetPoint("RIGHT", button, "RIGHT", 0, 0) | |
| 783 else | |
| 784 button = table.remove(buttons) | |
| 785 end | |
| 786 button:ClearAllPoints() | |
| 787 button:SetParent(level) | |
| 788 button:SetFrameStrata(level:GetFrameStrata()) | |
| 789 button:SetFrameLevel(level:GetFrameLevel() + 1) | |
| 790 button:SetPoint("LEFT", level, "LEFT", 10, 0) | |
| 791 button:SetPoint("RIGHT", level, "RIGHT", -10, 0) | |
| 792 if #level.buttons == 0 then | |
| 793 button:SetPoint("TOP", level, "TOP", 0, -10) | |
| 794 else | |
| 795 button:SetPoint("TOP", level.buttons[#level.buttons], "BOTTOM", 0, 0) | |
| 796 end | |
| 797 button.text:SetPoint("LEFT", button, "LEFT", 24, 0) | |
| 798 button:Show() | |
| 799 button.level = level | |
| 800 table.insert(level.buttons, button) | |
| 801 if not level.parented then | |
| 802 level.parented = true | |
| 803 level:ClearAllPoints() | |
| 804 if level.num == 1 then | |
| 805 if level.parent ~= UIParent and type(level.parent) == "table" then | |
| 806 level:SetPoint("TOPRIGHT", level.parent, "TOPLEFT") | |
| 807 else | |
| 808 level:SetPoint("CENTER", UIParent, "CENTER") | |
| 809 end | |
| 810 else | |
| 811 if level.lastDirection == "RIGHT" then | |
| 812 if level.lastVDirection == "DOWN" then | |
| 813 level:SetPoint("TOPLEFT", level.parent, "TOPRIGHT", 5, 10) | |
| 814 else | |
| 815 level:SetPoint("BOTTOMLEFT", level.parent, "BOTTOMRIGHT", 5, -10) | |
| 816 end | |
| 817 else | |
| 818 if level.lastVDirection == "DOWN" then | |
| 819 level:SetPoint("TOPRIGHT", level.parent, "TOPLEFT", -5, 10) | |
| 820 else | |
| 821 level:SetPoint("BOTTOMRIGHT", level.parent, "BOTTOMLEFT", -5, -10) | |
| 822 end | |
| 823 end | |
| 824 end | |
| 825 level:SetFrameStrata("FULLSCREEN_DIALOG") | |
| 826 end | |
| 827 button:SetAlpha(1) | |
| 828 return button | |
| 829 end | |
| 830 | |
| 831 local numLevels = 0 | |
| 832 local function AcquireLevel(self, level) | |
| 833 if not levels[level] then | |
| 834 for i = #levels + 1, level, -1 do | |
| 835 local i = i | |
| 836 numLevels = numLevels + 1 | |
| 837 local frame = CreateFrame("Button", "Dewdrop20Level" .. numLevels, nil) | |
| 838 if i == 1 then | |
| 839 local old_CloseSpecialWindows = CloseSpecialWindows | |
| 840 function CloseSpecialWindows() | |
| 841 local found = old_CloseSpecialWindows() | |
| 842 if levels[1]:IsShown() then | |
| 843 self:Close() | |
| 844 return 1 | |
| 845 end | |
| 846 return found | |
| 847 end | |
| 848 end | |
| 849 levels[i] = frame | |
| 850 frame.num = i | |
| 851 frame:SetParent(UIParent) | |
| 852 frame:SetFrameStrata("FULLSCREEN_DIALOG") | |
| 853 frame:Hide() | |
| 854 frame:SetWidth(180) | |
| 855 frame:SetHeight(10) | |
| 856 frame:SetFrameLevel(i * 3) | |
| 857 frame:SetScript("OnHide", function() | |
| 858 self:Close(level + 1) | |
| 859 end) | |
| 860 if frame.SetTopLevel then | |
| 861 frame:SetTopLevel(true) | |
| 862 end | |
| 863 frame:EnableMouse(true) | |
| 864 frame:EnableMouseWheel(true) | |
| 865 local backdrop = CreateFrame("Frame", nil, frame) | |
| 866 backdrop:SetAllPoints(frame) | |
| 867 backdrop:SetBackdrop(tmp( | |
| 868 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", | |
| 869 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", | |
| 870 'tile', true, | |
| 871 'insets', tmp2( | |
| 872 'left', 5, | |
| 873 'right', 5, | |
| 874 'top', 5, | |
| 875 'bottom', 5 | |
| 876 ), | |
| 877 'tileSize', 16, | |
| 878 'edgeSize', 16 | |
| 879 )) | |
| 880 backdrop:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) | |
| 881 backdrop:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) | |
| 882 frame:SetScript("OnClick", function() | |
| 883 self:Close(i) | |
| 884 end) | |
| 885 frame:SetScript("OnEnter", function() | |
| 886 StopCounting(self, i) | |
| 887 end) | |
| 888 frame:SetScript("OnLeave", function() | |
| 889 StartCounting(self, i) | |
| 890 end) | |
| 891 frame:SetScript("OnMouseWheel", function() | |
| 892 Scroll(self, frame, arg1 < 0) | |
| 893 end) | |
| 894 if i == 1 then | |
| 895 frame:SetScript("OnUpdate", function(this, arg1) | |
| 896 OnUpdate(self, arg1) | |
| 897 end) | |
| 898 levels[1].lastDirection = "RIGHT" | |
| 899 levels[1].lastVDirection = "DOWN" | |
| 900 else | |
| 901 levels[i].lastDirection = levels[i - 1].lastDirection | |
| 902 levels[i].lastVDirection = levels[i - 1].lastVDirection | |
| 903 end | |
| 904 end | |
| 905 end | |
| 906 local fullscreenFrame = GetUIPanel("fullscreen") | |
| 907 local l = levels[level] | |
| 908 local strata, framelevel = l:GetFrameStrata(), l:GetFrameLevel() | |
| 909 if fullscreenFrame then | |
| 910 l:SetParent(fullscreenFrame) | |
| 911 else | |
| 912 l:SetParent(UIParent) | |
| 913 end | |
| 914 l:SetFrameStrata(strata) | |
| 915 l:SetFrameLevel(framelevel) | |
| 916 l:SetAlpha(1) | |
| 917 return l | |
| 918 end | |
| 919 | |
| 920 local function validateOptions(options, position, baseOptions, fromPass) | |
| 921 if not baseOptions then | |
| 922 baseOptions = options | |
| 923 end | |
| 924 if type(options) ~= "table" then | |
| 925 return "Options must be a table.", position | |
| 926 end | |
| 927 local kind = options.type | |
| 928 if type(kind) ~= "string" then | |
| 929 return '"type" must be a string.', position | |
| 930 elseif kind ~= "group" and kind ~= "range" and kind ~= "text" and kind ~= "execute" and kind ~= "toggle" and kind ~= "color" and kind ~= "dragLink" and kind ~= "header" then | |
| 931 return '"type" must either be "range", "text", "group", "toggle", "execute", "color", "dragLink", or "header".', position | |
| 932 end | |
| 933 if options.aliases then | |
| 934 if type(options.aliases) ~= "table" and type(options.aliases) ~= "string" then | |
| 935 return '"alias" must be a table or string', position | |
| 936 end | |
| 937 end | |
| 938 if not fromPass then | |
| 939 if kind == "execute" then | |
| 940 if type(options.func) ~= "string" and type(options.func) ~= "function" then | |
| 941 return '"func" must be a string or function', position | |
| 942 end | |
| 943 elseif kind == "range" or kind == "text" or kind == "toggle" then | |
| 944 if type(options.set) ~= "string" and type(options.set) ~= "function" then | |
| 945 return '"set" must be a string or function', position | |
| 946 end | |
| 947 if kind == "text" and options.get == false then | |
| 948 elseif type(options.get) ~= "string" and type(options.get) ~= "function" then | |
| 949 return '"get" must be a string or function', position | |
| 950 end | |
| 951 elseif kind == "group" and options.pass then | |
| 952 if options.pass ~= true then | |
| 953 return '"pass" must be either nil, true, or false', position | |
| 954 end | |
| 955 if not options.func then | |
| 956 if type(options.set) ~= "string" and type(options.set) ~= "function" then | |
| 957 return '"set" must be a string or function', position | |
| 958 end | |
| 959 if type(options.get) ~= "string" and type(options.get) ~= "function" then | |
| 960 return '"get" must be a string or function', position | |
| 961 end | |
| 962 elseif type(options.func) ~= "string" and type(options.func) ~= "function" then | |
| 963 return '"func" must be a string or function', position | |
| 964 end | |
| 965 end | |
| 966 end | |
| 967 if options ~= baseOptions then | |
| 968 if kind == "header" then | |
| 969 elseif type(options.desc) ~= "string" then | |
| 970 return '"desc" must be a string', position | |
| 971 elseif options.desc:len() == 0 then | |
| 972 return '"desc" cannot be a 0-length string', position | |
| 973 end | |
| 974 end | |
| 975 if options ~= baseOptions or kind == "range" or kind == "text" or kind == "toggle" or kind == "color" then | |
| 976 if options.type == "header" and not options.cmdName and not options.name then | |
| 977 elseif options.cmdName then | |
| 978 if type(options.cmdName) ~= "string" then | |
| 979 return '"cmdName" must be a string or nil', position | |
| 980 elseif options.cmdName:len() == 0 then | |
| 981 return '"cmdName" cannot be a 0-length string', position | |
| 982 end | |
| 983 if type(options.guiName) ~= "string" then | |
| 984 if not options.guiNameIsMap then | |
| 985 return '"guiName" must be a string or nil', position | |
| 986 end | |
| 987 elseif options.guiName:len() == 0 then | |
| 988 return '"guiName" cannot be a 0-length string', position | |
| 989 end | |
| 990 else | |
| 991 if type(options.name) ~= "string" then | |
| 992 return '"name" must be a string', position | |
| 993 elseif options.name:len() == 0 then | |
| 994 return '"name" cannot be a 0-length string', position | |
| 995 end | |
| 996 end | |
| 997 end | |
| 998 if options.guiNameIsMap then | |
| 999 if type(options.guiNameIsMap) ~= "boolean" then | |
| 1000 return '"guiNameIsMap" must be a boolean or nil', position | |
| 1001 elseif options.type ~= "toggle" then | |
| 1002 return 'if "guiNameIsMap" is true, then "type" must be set to \'toggle\'', position | |
| 1003 elseif type(options.map) ~= "table" then | |
| 1004 return '"map" must be a table', position | |
| 1005 end | |
| 1006 end | |
| 1007 if options.message and type(options.message) ~= "string" then | |
| 1008 return '"message" must be a string or nil', position | |
| 1009 end | |
| 1010 if options.error and type(options.error) ~= "string" then | |
| 1011 return '"error" must be a string or nil', position | |
| 1012 end | |
| 1013 if options.current and type(options.current) ~= "string" then | |
| 1014 return '"current" must be a string or nil', position | |
| 1015 end | |
| 1016 if options.order then | |
| 1017 if type(options.order) ~= "number" or (-1 < options.order and options.order < 0.999) then | |
| 1018 return '"order" must be a non-zero number or nil', position | |
| 1019 end | |
| 1020 end | |
| 1021 if options.disabled then | |
| 1022 if type(options.disabled) ~= "function" and type(options.disabled) ~= "string" and options.disabled ~= true then | |
| 1023 return '"disabled" must be a function, string, or boolean', position | |
| 1024 end | |
| 1025 end | |
| 1026 if options.cmdHidden then | |
| 1027 if type(options.cmdHidden) ~= "function" and type(options.cmdHidden) ~= "string" and options.cmdHidden ~= true then | |
| 1028 return '"cmdHidden" must be a function, string, or boolean', position | |
| 1029 end | |
| 1030 end | |
| 1031 if options.guiHidden then | |
| 1032 if type(options.guiHidden) ~= "function" and type(options.guiHidden) ~= "string" and options.guiHidden ~= true then | |
| 1033 return '"guiHidden" must be a function, string, or boolean', position | |
| 1034 end | |
| 1035 end | |
| 1036 if options.hidden then | |
| 1037 if type(options.hidden) ~= "function" and type(options.hidden) ~= "string" and options.hidden ~= true then | |
| 1038 return '"hidden" must be a function, string, or boolean', position | |
| 1039 end | |
| 1040 end | |
| 1041 if kind == "text" then | |
| 1042 if type(options.validate) == "table" then | |
| 1043 local t = options.validate | |
| 1044 local iTable = nil | |
| 1045 for k,v in pairs(t) do | |
| 1046 if type(k) == "number" then | |
| 1047 if iTable == nil then | |
| 1048 iTable = true | |
| 1049 elseif not iTable then | |
| 1050 return '"validate" must either have all keys be indexed numbers or strings', position | |
| 1051 elseif k < 1 or k > #t then | |
| 1052 return '"validate" numeric keys must be indexed properly. >= 1 and <= #t', position | |
| 1053 end | |
| 1054 else | |
| 1055 if iTable == nil then | |
| 1056 iTable = false | |
| 1057 elseif iTable then | |
| 1058 return '"validate" must either have all keys be indexed numbers or strings', position | |
| 1059 end | |
| 1060 end | |
| 1061 if type(v) ~= "string" then | |
| 1062 return '"validate" values must all be strings', position | |
| 1063 end | |
| 1064 end | |
| 1065 if options.multiToggle and options.multiToggle ~= true then | |
| 1066 return '"multiToggle" must be a boolean or nil if "validate" is a table', position | |
| 1067 end | |
| 1068 elseif options.validate == "keybinding" then | |
| 1069 -- no other checks | |
| 1070 else | |
| 1071 if type(options.usage) ~= "string" then | |
| 1072 return '"usage" must be a string', position | |
| 1073 elseif options.validate and type(options.validate) ~= "string" and type(options.validate) ~= "function" then | |
| 1074 return '"validate" must be a string, function, or table', position | |
| 1075 end | |
| 1076 end | |
| 1077 if options.multiToggle and type(options.validate) ~= "table" then | |
| 1078 return '"validate" must be a table if "multiToggle" is true', position | |
| 1079 end | |
| 1080 elseif kind == "range" then | |
| 1081 if options.min or options.max then | |
| 1082 if type(options.min) ~= "number" then | |
| 1083 return '"min" must be a number', position | |
| 1084 elseif type(options.max) ~= "number" then | |
| 1085 return '"max" must be a number', position | |
| 1086 elseif options.min >= options.max then | |
| 1087 return '"min" must be less than "max"', position | |
| 1088 end | |
| 1089 end | |
| 1090 if options.step then | |
| 1091 if type(options.step) ~= "number" then | |
| 1092 return '"step" must be a number', position | |
| 1093 elseif options.step < 0 then | |
| 1094 return '"step" must be nonnegative', position | |
| 1095 end | |
| 1096 end | |
| 1097 if options.bigStep then | |
| 1098 if type(options.bigStep) ~= "number" then | |
| 1099 return '"bigStep" must be a number', position | |
| 1100 elseif options.bigStep < 0 then | |
| 1101 return '"bigStep" must be nonnegative', position | |
| 1102 end | |
| 1103 end | |
| 1104 if options.isPercent and options.isPercent ~= true then | |
| 1105 return '"isPercent" must either be nil, true, or false', position | |
| 1106 end | |
| 1107 elseif kind == "toggle" then | |
| 1108 if options.map then | |
| 1109 if type(options.map) ~= "table" then | |
| 1110 return '"map" must be a table', position | |
| 1111 elseif type(options.map[true]) ~= "string" then | |
| 1112 return '"map[true]" must be a string', position | |
| 1113 elseif type(options.map[false]) ~= "string" then | |
| 1114 return '"map[false]" must be a string', position | |
| 1115 end | |
| 1116 end | |
| 1117 elseif kind == "color" then | |
| 1118 if options.hasAlpha and options.hasAlpha ~= true then | |
| 1119 return '"hasAlpha" must be nil, true, or false', position | |
| 1120 end | |
| 1121 elseif kind == "group" then | |
| 1122 if options.pass and options.pass ~= true then | |
| 1123 return '"pass" must be nil, true, or false', position | |
| 1124 end | |
| 1125 if type(options.args) ~= "table" then | |
| 1126 return '"args" must be a table', position | |
| 1127 end | |
| 1128 for k,v in pairs(options.args) do | |
| 1129 if type(k) ~= "number" then | |
| 1130 if type(k) ~= "string" then | |
| 1131 return '"args" keys must be strings or numbers', position | |
| 1132 elseif k:len() == 0 then | |
| 1133 return '"args" keys must not be 0-length strings.', position | |
| 1134 end | |
| 1135 end | |
| 1136 if type(v) ~= "table" then | |
| 1137 return '"args" values must be tables', position and position .. "." .. k or k | |
| 1138 end | |
| 1139 local newposition | |
| 1140 if position then | |
| 1141 newposition = position .. ".args." .. k | |
| 1142 else | |
| 1143 newposition = "args." .. k | |
| 1144 end | |
| 1145 local err, pos = validateOptions(v, newposition, baseOptions, options.pass) | |
| 1146 if err then | |
| 1147 return err, pos | |
| 1148 end | |
| 1149 end | |
| 1150 elseif kind == "execute" then | |
| 1151 if type(options.confirm) ~= "string" and type(options.confirm) ~= "boolean" and type(options.confirm) ~= "nil" then | |
| 1152 return '"confirm" must be a string, boolean, or nil', position | |
| 1153 end | |
| 1154 end | |
| 1155 if options.icon and type(options.icon) ~= "string" then | |
| 1156 return'"icon" must be a string', position | |
| 1157 end | |
| 1158 if options.iconWidth or options.iconHeight then | |
| 1159 if type(options.iconWidth) ~= "number" or type(options.iconHeight) ~= "number" then | |
| 1160 return '"iconHeight" and "iconWidth" must be numbers', position | |
| 1161 end | |
| 1162 end | |
| 1163 if options.iconCoordLeft or options.iconCoordRight or options.iconCoordTop or options.iconCoordBottom then | |
| 1164 if type(options.iconCoordLeft) ~= "number" or type(options.iconCoordRight) ~= "number" or type(options.iconCoordTop) ~= "number" or type(options.iconCoordBottom) ~= "number" then | |
| 1165 return '"iconCoordLeft", "iconCoordRight", "iconCoordTop", and "iconCoordBottom" must be numbers', position | |
| 1166 end | |
| 1167 end | |
| 1168 end | |
| 1169 | |
| 1170 local validatedOptions | |
| 1171 | |
| 1172 local values | |
| 1173 local mysort_args | |
| 1174 local mysort | |
| 1175 local othersort | |
| 1176 local othersort_validate | |
| 1177 | |
| 1178 local baseFunc, currentLevel | |
| 1179 | |
| 1180 local function confirmPopup(message, func, ...) | |
| 1181 if not StaticPopupDialogs["DEWDROP20_CONFIRM_DIALOG"] then | |
| 1182 StaticPopupDialogs["DEWDROP20_CONFIRM_DIALOG"] = {} | |
| 1183 end | |
| 1184 local t = StaticPopupDialogs["DEWDROP20_CONFIRM_DIALOG"] | |
| 1185 for k in pairs(t) do | |
| 1186 t[k] = nil | |
| 1187 end | |
| 1188 t.text = message | |
| 1189 t.button1 = ACCEPT or "Accept" | |
| 1190 t.button2 = CANCEL or "Cancel" | |
| 1191 t.OnAccept = function() | |
| 1192 func(unpack(t)) | |
| 1193 end | |
| 1194 for i = 1, select('#', ...) do | |
| 1195 t[i] = select(i, ...) | |
| 1196 end | |
| 1197 t.timeout = 0 | |
| 1198 t.whileDead = 1 | |
| 1199 t.hideOnEscape = 1 | |
| 1200 | |
| 1201 Dewdrop:Close() | |
| 1202 StaticPopup_Show("DEWDROP20_CONFIRM_DIALOG") | |
| 1203 end | |
| 1204 | |
| 1205 | |
| 1206 local function getMethod(settingname, handler, v, methodName, ...) -- "..." is simply returned straight out cause you can't do "a,b,c = 111,f(),222" | |
| 1207 assert(v and type(v)=="table") | |
| 1208 assert(methodName and type(methodName)=="string") | |
| 1209 | |
| 1210 local method = v[methodName] | |
| 1211 if type(method)=="function" then | |
| 1212 return method, ... | |
| 1213 elseif type(method)=="string" then | |
| 1214 if not handler then | |
| 1215 Dewdrop:error("[%s] 'handler' is required if providing a method name: %q", tostring(settingname), method) | |
| 1216 elseif not handler[method] then | |
| 1217 Dewdrop:error("[%s] 'handler' method %q not defined", tostring(settingname), method) | |
| 1218 end | |
| 1219 return handler[method], handler, ... | |
| 1220 end | |
| 1221 | |
| 1222 Dewdrop:error("[%s] Missing %q directive", tostring(settingname), methodName) | |
| 1223 end | |
| 1224 | |
| 1225 local function callMethod(settingname, handler, v, methodName, ...) | |
| 1226 assert(v and type(v)=="table") | |
| 1227 assert(methodName and type(methodName)=="string") | |
| 1228 | |
| 1229 local method = v[methodName] | |
| 1230 if type(method)=="function" then | |
| 1231 local success, ret,ret2,ret3,ret4 = pcall(v[methodName], ...) | |
| 1232 if not success then | |
| 1233 geterrorhandler()(ret) | |
| 1234 return nil | |
| 1235 end | |
| 1236 return ret,ret2,ret3,ret4 | |
| 1237 | |
| 1238 elseif type(method)=="string" then | |
| 1239 | |
| 1240 local neg = method:match("^~(.-)$") | |
| 1241 if neg then | |
| 1242 method = neg | |
| 1243 end | |
| 1244 if not handler then | |
| 1245 Dewdrop:error("[%s] 'handler' is required if providing a method name: %q", tostring(settingname), method) | |
| 1246 elseif not handler[method] then | |
| 1247 Dewdrop:error("[%s] 'handler' (%q) method %q not defined", tostring(settingname), handler.name or "(unnamed)", method) | |
| 1248 end | |
| 1249 local success, ret,ret2,ret3,ret4 = pcall(handler[method], handler, ...) | |
| 1250 if not success then | |
| 1251 geterrorhandler()(ret) | |
| 1252 return nil | |
| 1253 end | |
| 1254 if neg then | |
| 1255 return not ret | |
| 1256 end | |
| 1257 return ret,ret2,ret3,ret4 | |
| 1258 elseif method == false then | |
| 1259 return nil | |
| 1260 end | |
| 1261 | |
| 1262 Dewdrop:error("[%s] Missing %q directive in %q", tostring(settingname), methodName, v.name or "(unnamed)") | |
| 1263 end | |
| 1264 | |
| 1265 local function skip1Nil(...) | |
| 1266 if select(1,...)==nil then | |
| 1267 return select(2,...) | |
| 1268 end | |
| 1269 return ... | |
| 1270 end | |
| 1271 | |
| 1272 function Dewdrop:FeedAceOptionsTable(options, difference) | |
| 1273 self:argCheck(options, 2, "table") | |
| 1274 self:argCheck(difference, 3, "nil", "number") | |
| 1275 if not currentLevel then | |
| 1276 self:error("Cannot call `FeedAceOptionsTable' outside of a Dewdrop declaration") | |
| 1277 end | |
| 1278 if not difference then | |
| 1279 difference = 0 | |
| 1280 end | |
| 1281 if not validatedOptions then | |
| 1282 validatedOptions = {} | |
| 1283 end | |
| 1284 if not validatedOptions[options] then | |
| 1285 local err, position = validateOptions(options) | |
| 1286 | |
| 1287 if err then | |
| 1288 if position then | |
| 1289 Dewdrop:error(position .. ": " .. err) | |
| 1290 else | |
| 1291 Dewdrop:error(err) | |
| 1292 end | |
| 1293 end | |
| 1294 | |
| 1295 validatedOptions[options] = true | |
| 1296 end | |
| 1297 local level = levels[currentLevel] | |
| 1298 if not level then | |
| 1299 self:error("Improper level given") | |
| 1300 end | |
| 1301 if not values then | |
| 1302 values = {} | |
| 1303 else | |
| 1304 for k,v in pairs(values) do | |
| 1305 values[k] = nil | |
| 1306 end | |
| 1307 end | |
| 1308 | |
| 1309 local current = level | |
| 1310 while current do -- this traverses from higher level numbers to lower, building "values" with leaf nodes first and trunk nodes later | |
| 1311 if current.num == difference + 1 then | |
| 1312 break | |
| 1313 end | |
| 1314 table.insert(values, current.value) | |
| 1315 current = levels[current.num - 1] | |
| 1316 end | |
| 1317 | |
| 1318 local realOptions = options | |
| 1319 local handler = options.handler | |
| 1320 local passTable | |
| 1321 local passValue | |
| 1322 while #values > 0 do -- This loop traverses values from the END (trunk nodes first, then onto leaf nodes) | |
| 1323 if options.pass then | |
| 1324 if options.get and options.set then | |
| 1325 passTable = options | |
| 1326 elseif not passTable then | |
| 1327 passTable = options | |
| 1328 end | |
| 1329 else | |
| 1330 passTable = nil | |
| 1331 end | |
| 1332 local value = table.remove(values) | |
| 1333 options = options.args and options.args[value] | |
| 1334 if not options then | |
| 1335 return | |
| 1336 end | |
| 1337 handler = options.handler or handler | |
| 1338 passValue = passTable and value or nil | |
| 1339 end | |
| 1340 | |
| 1341 if options.type == "group" then | |
| 1342 local hidden = options.hidden | |
| 1343 if type(hidden) == "function" or type(hidden) == "string" then | |
| 1344 hidden = callMethod(options.name or "(options root)", handler, options, "hidden", options.passValue) or false | |
| 1345 end | |
| 1346 if hidden then | |
| 1347 return | |
| 1348 end | |
| 1349 local disabled = options.disabled | |
| 1350 if type(disabled) == "function" or type(disabled) == "string" then | |
| 1351 disabled = callMethod(options.name or "(options root)", handler, options, "disabled", options.passValue) or false | |
| 1352 end | |
| 1353 if disabled then | |
| 1354 self:AddLine( | |
| 1355 'text', DISABLED, | |
| 1356 'disabled', true | |
| 1357 ) | |
| 1358 return | |
| 1359 end | |
| 1360 for k in pairs(options.args) do | |
| 1361 table.insert(values, k) | |
| 1362 end | |
| 1363 if options.pass then | |
| 1364 if options.get and options.set then | |
| 1365 passTable = options | |
| 1366 elseif not passTable then | |
| 1367 passTable = options | |
| 1368 end | |
| 1369 else | |
| 1370 passTable = nil | |
| 1371 end | |
| 1372 if not mysort then | |
| 1373 mysort = function(a, b) | |
| 1374 local alpha, bravo = mysort_args[a], mysort_args[b] | |
| 1375 local alpha_order = alpha.order or 100 | |
| 1376 local bravo_order = bravo.order or 100 | |
| 1377 local alpha_name = alpha.guiName or alpha.name | |
| 1378 local bravo_name = bravo.guiName or bravo.name | |
| 1379 if alpha_order == bravo_order then | |
| 1380 if not alpha_name then | |
| 1381 return bravo_name | |
| 1382 elseif not bravo_name then | |
| 1383 return false | |
| 1384 else | |
| 1385 return alpha_name:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):upper() < bravo_name:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):upper() | |
| 1386 end | |
| 1387 else | |
| 1388 if alpha_order < 0 then | |
| 1389 if bravo_order > 0 then | |
| 1390 return false | |
| 1391 end | |
| 1392 else | |
| 1393 if bravo_order < 0 then | |
| 1394 return true | |
| 1395 end | |
| 1396 end | |
| 1397 return alpha_order < bravo_order | |
| 1398 end | |
| 1399 end | |
| 1400 end | |
| 1401 mysort_args = options.args | |
| 1402 table.sort(values, mysort) | |
| 1403 mysort_args = nil | |
| 1404 local hasBoth = #values >= 1 and (options.args[values[1]].order or 100) > 0 and (options.args[values[#values]].order or 100) < 0 | |
| 1405 local last_order = 1 | |
| 1406 for _,k in ipairs(values) do | |
| 1407 local v = options.args[k] | |
| 1408 local handler = v.handler or handler | |
| 1409 if hasBoth and last_order > 0 and (v.order or 100) < 0 then | |
| 1410 hasBoth = false | |
| 1411 self:AddLine() | |
| 1412 end | |
| 1413 local hidden, disabled = v.guiHidden or v.hidden, v.disabled | |
| 1414 | |
| 1415 if type(hidden) == "function" or type(hidden) == "string" then | |
| 1416 hidden = callMethod(k, handler, v, "hidden", v.passValue) or false | |
| 1417 end | |
| 1418 if not hidden then | |
| 1419 if type(disabled) == "function" or type(disabled) == "string" then | |
| 1420 disabled = callMethod(k, handler, v, "disabled", v.passValue) or false | |
| 1421 end | |
| 1422 local name = (v.guiIconOnly and v.icon) and "" or (v.guiName or v.name) | |
| 1423 local desc = v.guiDesc or v.desc | |
| 1424 local iconHeight = v.iconHeight or 16 | |
| 1425 local iconWidth = v.iconWidth or 16 | |
| 1426 local iconCoordLeft = v.iconCoordLeft | |
| 1427 local iconCoordRight = v.iconCoordRight | |
| 1428 local iconCoordBottom = v.iconCoordBottom | |
| 1429 local iconCoordTop = v.iconCoordTop | |
| 1430 local tooltipTitle, tooltipText | |
| 1431 tooltipTitle = name | |
| 1432 if name ~= desc then | |
| 1433 tooltipText = desc | |
| 1434 end | |
| 1435 if type(v.usage) == "string" and v.usage:trim():len() > 0 then | |
| 1436 if tooltipText then | |
| 1437 tooltipText = tooltipText .. "\n\n" .. USAGE_TOOLTIP:format(v.usage) | |
| 1438 else | |
| 1439 tooltipText = USAGE_TOOLTIP:format(v.usage) | |
| 1440 end | |
| 1441 end | |
| 1442 local v_p = passTable | |
| 1443 if not v_p or (v.type ~= "execute" and v.get and v.set) or (v.type == "execute" and v.func) then | |
| 1444 v_p = v | |
| 1445 end | |
| 1446 local passValue = v.passValue or (v_p~=v and k) or nil | |
| 1447 if v.type == "toggle" then | |
| 1448 local checked = callMethod(name, handler, v_p, "get", passValue) or false | |
| 1449 local checked_arg = checked | |
| 1450 if type(v_p.get)=="string" and v_p.get:match("^~") then | |
| 1451 checked_arg = not checked | |
| 1452 end | |
| 1453 local func, arg1, arg2, arg3 = getMethod(name, handler, v_p, "set", skip1Nil(passValue, not checked_arg)) | |
| 1454 if v.guiNameIsMap then | |
| 1455 checked = checked and true or false | |
| 1456 name = tostring(v.map and v.map[checked]):gsub("|c%x%x%x%x%x%x%x%x(.-)|r", "%1") | |
| 1457 tooltipTitle = name | |
| 1458 checked = true--nil | |
| 1459 end | |
| 1460 self:AddLine( | |
| 1461 'text', name, | |
| 1462 'checked', checked, | |
| 1463 'isRadio', v.isRadio, | |
| 1464 'func', func, | |
| 1465 'arg1', arg1, | |
| 1466 'arg2', arg2, | |
| 1467 'arg3', arg3, | |
| 1468 'disabled', disabled, | |
| 1469 'tooltipTitle', tooltipTitle, | |
| 1470 'tooltipText', tooltipText | |
| 1471 ) | |
| 1472 elseif v.type == "execute" then | |
| 1473 local func, arg1, arg2, arg3, arg4 | |
| 1474 local confirm = v.confirm | |
| 1475 if confirm == true then | |
| 1476 confirm = DEFAULT_CONFIRM_MESSAGE:format(tooltipText or tooltipTitle) | |
| 1477 func,arg1,arg2,arg3,arg4 = confirmPopup, confirm, getMethod(name, handler, v_p, "func", passValue) | |
| 1478 elseif type(confirm) == "string" then | |
| 1479 func,arg1,arg2,arg3,arg4 = confirmPopup, confirm, getMethod(name, handler, v_p, "func", passValue) | |
| 1480 else | |
| 1481 func,arg1,arg2 = getMethod(name, handler, v_p, "func", passValue) | |
| 1482 end | |
| 1483 self:AddLine( | |
| 1484 'text', name, | |
| 1485 'checked', checked, | |
| 1486 'func', func, | |
| 1487 'arg1', arg1, | |
| 1488 'arg2', arg2, | |
| 1489 'arg3', arg3, | |
| 1490 'arg4', arg4, | |
| 1491 'disabled', disabled, | |
| 1492 'tooltipTitle', tooltipTitle, | |
| 1493 'tooltipText', tooltipText, | |
| 1494 'icon', v.icon, | |
| 1495 'iconHeight', iconHeight, | |
| 1496 'iconWidth', iconWidth, | |
| 1497 'iconCoordLeft', iconCoordLeft, | |
| 1498 'iconCoordRight', iconCoordRight, | |
| 1499 'iconCoordTop', iconCoordTop, | |
| 1500 'iconCoordBottom', iconCoordBottom | |
| 1501 ) | |
| 1502 elseif v.type == "range" then | |
| 1503 local sliderValue | |
| 1504 sliderValue = callMethod(name, handler, v_p, "get", passValue) or 0 | |
| 1505 local sliderFunc, sliderArg1, sliderArg2 = getMethod(name, handler, v_p, "set", passValue) | |
| 1506 if tooltipText then | |
| 1507 tooltipText = format("%s\n\n%s", tooltipText, RANGE_TOOLTIP) | |
| 1508 else | |
| 1509 tooltipText = RANGE_TOOLTIP | |
| 1510 end | |
| 1511 self:AddLine( | |
| 1512 'text', name, | |
| 1513 'hasArrow', true, | |
| 1514 'hasSlider', true, | |
| 1515 'sliderMin', v.min or 0, | |
| 1516 'sliderMax', v.max or 1, | |
| 1517 'sliderStep', v.step or 0, | |
| 1518 'sliderBigStep', v.bigStep or nil, | |
| 1519 'sliderIsPercent', v.isPercent or false, | |
| 1520 'sliderValue', sliderValue, | |
| 1521 'sliderFunc', sliderFunc, | |
| 1522 'sliderArg1', sliderArg1, | |
| 1523 'sliderArg2', sliderArg2, | |
| 1524 'fromAceOptions', true, | |
| 1525 'disabled', disabled, | |
| 1526 'tooltipTitle', tooltipTitle, | |
| 1527 'tooltipText', tooltipText, | |
| 1528 'icon', v.icon, | |
| 1529 'iconHeight', iconHeight, | |
| 1530 'iconWidth', iconWidth, | |
| 1531 'iconCoordLeft', iconCoordLeft, | |
| 1532 'iconCoordRight', iconCoordRight, | |
| 1533 'iconCoordTop', iconCoordTop, | |
| 1534 'iconCoordBottom', iconCoordBottom | |
| 1535 ) | |
| 1536 elseif v.type == "color" then | |
| 1537 local r,g,b,a = callMethod(name, handler, v_p, "get", passValue) | |
| 1538 if not r then | |
| 1539 r,g,b,a = 0,0,0,0 | |
| 1540 end | |
| 1541 local colorFunc, colorArg1, colorArg2 = getMethod(name, handler, v_p, "set", passValue) | |
| 1542 self:AddLine( | |
| 1543 'text', name, | |
| 1544 'hasArrow', true, | |
| 1545 'hasColorSwatch', true, | |
| 1546 'r', r, | |
| 1547 'g', g, | |
| 1548 'b', b, | |
| 1549 'opacity', v.hasAlpha and a or nil, | |
| 1550 'hasOpacity', v.hasAlpha, | |
| 1551 'colorFunc', colorFunc, | |
| 1552 'colorArg1', colorArg1, | |
| 1553 'colorArg2', colorArg2, | |
| 1554 'disabled', disabled, | |
| 1555 'tooltipTitle', tooltipTitle, | |
| 1556 'tooltipText', tooltipText | |
| 1557 ) | |
| 1558 elseif v.type == "text" then | |
| 1559 if type(v.validate) == "table" then | |
| 1560 local func,arg1,arg2 | |
| 1561 if v.onClick then | |
| 1562 func,arg1,arg2 = getMethod(name, handler, v, "onClick", passValue) | |
| 1563 end | |
| 1564 local checked | |
| 1565 if v.isChecked then | |
| 1566 checked = callMethod(name, handler, v, "isChecked", passValue) or false | |
| 1567 end | |
| 1568 self:AddLine( | |
| 1569 'text', name, | |
| 1570 'hasArrow', true, | |
| 1571 'value', k, | |
| 1572 'func', func, | |
| 1573 'arg1', arg1, | |
| 1574 'arg2', arg2, | |
| 1575 'mouseoverUnderline', func and true or nil, | |
| 1576 'disabled', disabled, | |
| 1577 'checked', checked, | |
| 1578 'tooltipTitle', tooltipTitle, | |
| 1579 'tooltipText', tooltipText, | |
| 1580 'icon', v.icon, | |
| 1581 'iconHeight', iconHeight, | |
| 1582 'iconWidth', iconWidth, | |
| 1583 'iconCoordLeft', iconCoordLeft, | |
| 1584 'iconCoordRight', iconCoordRight, | |
| 1585 'iconCoordTop', iconCoordTop, | |
| 1586 'iconCoordBottom', iconCoordBottom | |
| 1587 ) | |
| 1588 else | |
| 1589 local editBoxText | |
| 1590 editBoxText = callMethod(name, handler, v_p, "get", passValue) or "" | |
| 1591 local editBoxFunc, editBoxArg1, editBoxArg2 = getMethod(name, handler, v_p, "set", passValue) | |
| 1592 | |
| 1593 local editBoxValidateFunc, editBoxValidateArg1 | |
| 1594 | |
| 1595 if v.validate and v.validate ~= "keybinding" then | |
| 1596 if v.validate == "keybinding" then | |
| 1597 if tooltipText then | |
| 1598 tooltipText = format("%s\n\n%s", tooltipText, RESET_KEYBINDING_DESC) | |
| 1599 else | |
| 1600 tooltipText = RESET_KEYBINDING_DESC | |
| 1601 end | |
| 1602 else | |
| 1603 editBoxValidateFunc, editBoxValidateArg1 = getMethod(name, handler, v, "validate") -- no passvalue! | |
| 1604 end | |
| 1605 end | |
| 1606 | |
| 1607 self:AddLine( | |
| 1608 'text', name, | |
| 1609 'hasArrow', true, | |
| 1610 'icon', v.icon, | |
| 1611 'iconHeight', iconHeight, | |
| 1612 'iconWidth', iconWidth, | |
| 1613 'iconCoordLeft', iconCoordLeft, | |
| 1614 'iconCoordRight', iconCoordRight, | |
| 1615 'iconCoordTop', iconCoordTop, | |
| 1616 'iconCoordBottom', iconCoordBottom, | |
| 1617 'hasEditBox', true, | |
| 1618 'editBoxText', editBoxText, | |
| 1619 'editBoxFunc', editBoxFunc, | |
| 1620 'editBoxArg1', editBoxArg1, | |
| 1621 'editBoxArg2', editBoxArg2, | |
| 1622 'editBoxValidateFunc', editBoxValidateFunc, | |
| 1623 'editBoxValidateArg1', editBoxValidateArg1, | |
| 1624 'editBoxIsKeybinding', v.validate == "keybinding", | |
| 1625 'editBoxKeybindingOnly', v.keybindingOnly, | |
| 1626 'editBoxKeybindingExcept', v.keybindingExcept, | |
| 1627 'disabled', disabled, | |
| 1628 'tooltipTitle', tooltipTitle, | |
| 1629 'tooltipText', tooltipText | |
| 1630 ) | |
| 1631 end | |
| 1632 elseif v.type == "group" then | |
| 1633 local func,arg1,arg2 | |
| 1634 if v.onClick then | |
| 1635 func,arg1,arg2 = getMethod(name, handler, v, "onClick", passValue) | |
| 1636 end | |
| 1637 local checked | |
| 1638 if v.isChecked then | |
| 1639 checked = callMethod(name, handler, v, "isChecked", passValue) or false | |
| 1640 end | |
| 1641 self:AddLine( | |
| 1642 'text', name, | |
| 1643 'hasArrow', true, | |
| 1644 'value', k, | |
| 1645 'func', func, | |
| 1646 'arg1', arg1, | |
| 1647 'arg2', arg2, | |
| 1648 'mouseoverUnderline', func and true or nil, | |
| 1649 'disabled', disabled, | |
| 1650 'checked', checked, | |
| 1651 'tooltipTitle', tooltipTitle, | |
| 1652 'tooltipText', tooltipText, | |
| 1653 'icon', v.icon, | |
| 1654 'iconHeight', iconHeight, | |
| 1655 'iconWidth', iconWidth, | |
| 1656 'iconCoordLeft', iconCoordLeft, | |
| 1657 'iconCoordRight', iconCoordRight, | |
| 1658 'iconCoordTop', iconCoordTop, | |
| 1659 'iconCoordBottom', iconCoordBottom | |
| 1660 ) | |
| 1661 elseif v.type == "header" then | |
| 1662 if name == "" or not name then | |
| 1663 self:AddLine( | |
| 1664 'isTitle', true, | |
| 1665 'icon', v.icon, | |
| 1666 'iconHeight', iconHeight, | |
| 1667 'iconWidth', iconWidth, | |
| 1668 'iconCoordLeft', iconCoordLeft, | |
| 1669 'iconCoordRight', iconCoordRight, | |
| 1670 'iconCoordTop', iconCoordTop, | |
| 1671 'iconCoordBottom', iconCoordBottom | |
| 1672 ) | |
| 1673 else | |
| 1674 self:AddLine( | |
| 1675 'text', name, | |
| 1676 'isTitle', true, | |
| 1677 'icon', v.icon, | |
| 1678 'iconHeight', iconHeight, | |
| 1679 'iconWidth', iconWidth, | |
| 1680 'iconCoordLeft', iconCoordLeft, | |
| 1681 'iconCoordRight', iconCoordRight, | |
| 1682 'iconCoordTop', iconCoordTop, | |
| 1683 'iconCoordBottom', iconCoordBottom | |
| 1684 ) | |
| 1685 end | |
| 1686 end | |
| 1687 end | |
| 1688 last_order = v.order or 100 | |
| 1689 end | |
| 1690 elseif options.type == "text" and type(options.validate) == "table" then | |
| 1691 local current | |
| 1692 local options_p = passTable | |
| 1693 if not options_p or (options.get and options.set) then | |
| 1694 options_p = options | |
| 1695 passTable = nil | |
| 1696 passValue = nil | |
| 1697 end | |
| 1698 local multiToggle = options.multiToggle | |
| 1699 local passValue = options.passValue or passValue | |
| 1700 if not multiToggle then | |
| 1701 current = callMethod(k, handler, options_p, "get", passValue) | |
| 1702 end | |
| 1703 local indexed = true | |
| 1704 for k,v in pairs(options.validate) do | |
| 1705 if type(k) ~= "number" then | |
| 1706 indexed = false | |
| 1707 end | |
| 1708 table.insert(values, k) | |
| 1709 end | |
| 1710 if not indexed then | |
| 1711 if not othersort then | |
| 1712 othersort = function(alpha, bravo) | |
| 1713 return othersort_validate[alpha]:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):upper() < othersort_validate[bravo]:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):upper() | |
| 1714 end | |
| 1715 end | |
| 1716 othersort_validate = options.validate | |
| 1717 table.sort(values, othersort) | |
| 1718 othersort_validate = nil | |
| 1719 end | |
| 1720 for _,k in ipairs(values) do | |
| 1721 local v = options.validate[k] | |
| 1722 if type(k) == "number" then | |
| 1723 k = v | |
| 1724 end | |
| 1725 local func, arg1, arg2, arg3, arg4 = getMethod(k, handler, options_p, "set", skip1Nil(passValue, k)) | |
| 1726 local checked | |
| 1727 if multiToggle then | |
| 1728 checked = callMethod(k, handler, options_p, "get", skip1Nil(passValue, k)) or false | |
| 1729 if arg2 == nil then | |
| 1730 arg2 = not checked | |
| 1731 elseif arg3 == nil then | |
| 1732 arg3 = not checked | |
| 1733 else | |
| 1734 arg4 = not checked | |
| 1735 end | |
| 1736 else | |
| 1737 checked = (k == current or (type(k) == "string" and type(current) == "string" and k:lower() == current:lower())) | |
| 1738 if checked then | |
| 1739 func, arg1, arg2, arg3, arg4 = nil, nil, nil, nil, nil | |
| 1740 end | |
| 1741 end | |
| 1742 local tooltipTitle | |
| 1743 local tooltipText | |
| 1744 if options.validateDesc then | |
| 1745 tooltipTitle = v | |
| 1746 tooltipText = options.validateDesc[k] | |
| 1747 else | |
| 1748 tooltipTitle = options.guiName or options.name | |
| 1749 tooltipText = v | |
| 1750 end | |
| 1751 self:AddLine( | |
| 1752 'text', v, | |
| 1753 'func', func, | |
| 1754 'arg1', arg1, | |
| 1755 'arg2', arg2, | |
| 1756 'arg3', arg3, | |
| 1757 'arg4', arg4, | |
| 1758 'isRadio', not multiToggle, | |
| 1759 'checked', checked, | |
| 1760 'tooltipTitle', tooltipTitle, | |
| 1761 'tooltipText', tooltipText | |
| 1762 ) | |
| 1763 end | |
| 1764 for k in pairs(values) do | |
| 1765 values[k] = nil | |
| 1766 end | |
| 1767 else | |
| 1768 return false | |
| 1769 end | |
| 1770 return true | |
| 1771 end | |
| 1772 | |
| 1773 function Dewdrop:FeedTable(s, difference) | |
| 1774 self:argCheck(s, 2, "table") | |
| 1775 self:argCheck(difference, 3, "nil", "number") | |
| 1776 if not currentLevel then | |
| 1777 self:error("Cannot call `FeedTable' outside of a Dewdrop declaration") | |
| 1778 end | |
| 1779 if not difference then | |
| 1780 difference = 0 | |
| 1781 end | |
| 1782 local level = levels[currentLevel] | |
| 1783 if not level then | |
| 1784 self:error("Improper level given") | |
| 1785 end | |
| 1786 if not values then | |
| 1787 values = {} | |
| 1788 else | |
| 1789 for k,v in pairs(values) do | |
| 1790 values[k] = nil | |
| 1791 end | |
| 1792 end | |
| 1793 local t = s.subMenu and s or {subMenu = s} | |
| 1794 local current = level | |
| 1795 while current do | |
| 1796 if current.num == difference + 1 then | |
| 1797 break | |
| 1798 end | |
| 1799 table.insert(values, current.value) | |
| 1800 current = levels[current.num - 1] | |
| 1801 end | |
| 1802 | |
| 1803 while #values > 0 do | |
| 1804 local value = table.remove(values) | |
| 1805 t = t.subMenu and t.subMenu[value] | |
| 1806 if not t then | |
| 1807 return | |
| 1808 end | |
| 1809 end | |
| 1810 | |
| 1811 if t.subMenu or current.num == 1 then | |
| 1812 for k in pairs(t.subMenu) do | |
| 1813 table.insert(values, k) | |
| 1814 end | |
| 1815 table.sort(values) | |
| 1816 for _,k in ipairs(values) do | |
| 1817 local argTable = {"value", k} | |
| 1818 for key, val in pairs(t.subMenu[k]) do | |
| 1819 table.insert(argTable, key) | |
| 1820 table.insert(argTable, val) | |
| 1821 end | |
| 1822 self:AddLine(unpack(argTable)) | |
| 1823 end | |
| 1824 for k in pairs(values) do | |
| 1825 values[k] = nil | |
| 1826 end | |
| 1827 return false | |
| 1828 end | |
| 1829 return true | |
| 1830 end | |
| 1831 | |
| 1832 function Refresh(self, level) | |
| 1833 if type(level) == "number" then | |
| 1834 level = levels[level] | |
| 1835 end | |
| 1836 if not level then | |
| 1837 return | |
| 1838 end | |
| 1839 if baseFunc then | |
| 1840 Clear(self, level) | |
| 1841 currentLevel = level.num | |
| 1842 if type(baseFunc) == "table" then | |
| 1843 if currentLevel == 1 then | |
| 1844 local handler = baseFunc.handler | |
| 1845 if handler then | |
| 1846 local name = tostring(handler) | |
| 1847 if not name:find('^table:') and not handler.hideMenuTitle then | |
| 1848 name = name:gsub("|c%x%x%x%x%x%x%x%x(.-)|r", "%1") | |
| 1849 self:AddLine( | |
| 1850 'text', name, | |
| 1851 'isTitle', true | |
| 1852 ) | |
| 1853 end | |
| 1854 end | |
| 1855 -- elseif level.parentText then | |
| 1856 -- self:AddLine( | |
| 1857 -- 'text', level.parentText, | |
| 1858 -- 'tooltipTitle', level.parentTooltipTitle, | |
| 1859 -- 'tooltipText', level.parentTooltipText, | |
| 1860 -- 'tooltipFunc', level.parentTooltipFunc, | |
| 1861 -- 'isTitle', true | |
| 1862 -- ) | |
| 1863 end | |
| 1864 self:FeedAceOptionsTable(baseFunc) | |
| 1865 if currentLevel == 1 then | |
| 1866 self:AddLine( | |
| 1867 'text', CLOSE, | |
| 1868 'tooltipTitle', CLOSE, | |
| 1869 'tooltipText', CLOSE_DESC, | |
| 1870 'closeWhenClicked', true | |
| 1871 ) | |
| 1872 end | |
| 1873 else | |
| 1874 -- if level.parentText then | |
| 1875 -- self:AddLine( | |
| 1876 -- 'text', level.parentText, | |
| 1877 -- 'tooltipTitle', level.parentTooltipTitle, | |
| 1878 -- 'tooltipText', level.parentTooltipText, | |
| 1879 -- 'tooltipFunc', level.parentTooltipFunc, | |
| 1880 -- 'isTitle', true | |
| 1881 -- ) | |
| 1882 -- end | |
| 1883 baseFunc(currentLevel, level.value, levels[level.num - 1] and levels[level.num - 1].value, levels[level.num - 2] and levels[level.num - 2].value, levels[level.num - 3] and levels[level.num - 3].value, levels[level.num - 4] and levels[level.num - 4].value) | |
| 1884 end | |
| 1885 currentLevel = nil | |
| 1886 CheckSize(self, level) | |
| 1887 end | |
| 1888 end | |
| 1889 | |
| 1890 function Dewdrop:Refresh(level) | |
| 1891 self:argCheck(level, 2, "number", "nil") | |
| 1892 if not level then | |
| 1893 for k,v in pairs(levels) do | |
| 1894 Refresh(self, v) | |
| 1895 end | |
| 1896 else | |
| 1897 Refresh(self, levels[level]) | |
| 1898 end | |
| 1899 end | |
| 1900 | |
| 1901 function OpenSlider(self, parent) | |
| 1902 if not sliderFrame then | |
| 1903 sliderFrame = CreateFrame("Frame", nil, nil) | |
| 1904 sliderFrame:SetWidth(100) | |
| 1905 sliderFrame:SetHeight(170) | |
| 1906 sliderFrame:SetScale(UIParent:GetScale()) | |
| 1907 sliderFrame:SetBackdrop(tmp( | |
| 1908 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", | |
| 1909 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", | |
| 1910 'tile', true, | |
| 1911 'insets', tmp2( | |
| 1912 'left', 5, | |
| 1913 'right', 5, | |
| 1914 'top', 5, | |
| 1915 'bottom', 5 | |
| 1916 ), | |
| 1917 'tileSize', 16, | |
| 1918 'edgeSize', 16 | |
| 1919 )) | |
| 1920 sliderFrame:SetFrameStrata("FULLSCREEN_DIALOG") | |
| 1921 if sliderFrame.SetTopLevel then | |
| 1922 sliderFrame:SetTopLevel(true) | |
| 1923 end | |
| 1924 sliderFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) | |
| 1925 sliderFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) | |
| 1926 sliderFrame:EnableMouse(true) | |
| 1927 sliderFrame:EnableMouseWheel(true) | |
| 1928 sliderFrame:Hide() | |
| 1929 sliderFrame:SetPoint("CENTER", UIParent, "CENTER") | |
| 1930 local slider = CreateFrame("Slider", nil, sliderFrame) | |
| 1931 sliderFrame.slider = slider | |
| 1932 slider:SetOrientation("VERTICAL") | |
| 1933 slider:SetMinMaxValues(0, 1) | |
| 1934 slider:SetValueStep(0.000000001) | |
| 1935 slider:SetValue(0.5) | |
| 1936 slider:SetWidth(16) | |
| 1937 slider:SetHeight(128) | |
| 1938 slider:SetPoint("LEFT", sliderFrame, "LEFT", 15, 0) | |
| 1939 slider:SetBackdrop(tmp( | |
| 1940 'bgFile', "Interface\\Buttons\\UI-SliderBar-Background", | |
| 1941 'edgeFile', "Interface\\Buttons\\UI-SliderBar-Border", | |
| 1942 'tile', true, | |
| 1943 'edgeSize', 8, | |
| 1944 'tileSize', 8, | |
| 1945 'insets', tmp2( | |
| 1946 'left', 3, | |
| 1947 'right', 3, | |
| 1948 'top', 3, | |
| 1949 'bottom', 3 | |
| 1950 ) | |
| 1951 )) | |
| 1952 local texture = slider:CreateTexture() | |
| 1953 slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical") | |
| 1954 local text = slider:CreateFontString(nil, "ARTWORK") | |
| 1955 sliderFrame.topText = text | |
| 1956 text:SetFontObject(GameFontGreenSmall) | |
| 1957 text:SetText("100%") | |
| 1958 text:SetPoint("BOTTOM", slider, "TOP") | |
| 1959 local text = slider:CreateFontString(nil, "ARTWORK") | |
| 1960 sliderFrame.bottomText = text | |
| 1961 text:SetFontObject(GameFontGreenSmall) | |
| 1962 text:SetText("0%") | |
| 1963 text:SetPoint("TOP", slider, "BOTTOM") | |
| 1964 local editBox = CreateFrame("EditBox", nil, sliderFrame) | |
| 1965 sliderFrame.currentText = editBox | |
| 1966 editBox:SetFontObject(ChatFontNormal) | |
| 1967 editBox:SetHeight(13) | |
| 1968 editBox:SetPoint("RIGHT", sliderFrame, "RIGHT", -16, 0) | |
| 1969 editBox:SetPoint("LEFT", slider, "RIGHT", 12, 0) | |
| 1970 editBox:SetText("50%") | |
| 1971 editBox:SetJustifyH("CENTER") | |
| 1972 | |
| 1973 local width = editBox:GetWidth()/2 + 10 | |
| 1974 local left = editBox:CreateTexture(nil, "BACKGROUND") | |
| 1975 left:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Left") | |
| 1976 left:SetTexCoord(0, width / 256, 0, 1) | |
| 1977 left:SetWidth(width) | |
| 1978 left:SetHeight(32) | |
| 1979 left:SetPoint("LEFT", editBox, "LEFT", -10, 0) | |
| 1980 local right = editBox:CreateTexture(nil, "BACKGROUND") | |
| 1981 right:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Right") | |
| 1982 right:SetTexCoord(1 - width / 256, 1, 0, 1) | |
| 1983 right:SetWidth(width) | |
| 1984 right:SetHeight(32) | |
| 1985 right:SetPoint("RIGHT", editBox, "RIGHT", 10, 0) | |
| 1986 | |
| 1987 local changed = false | |
| 1988 local inside = false | |
| 1989 slider:SetScript("OnValueChanged", function() | |
| 1990 if sliderFrame.changing then | |
| 1991 return | |
| 1992 end | |
| 1993 changed = true | |
| 1994 local done = false | |
| 1995 if sliderFrame.parent and sliderFrame.parent.sliderFunc then | |
| 1996 local min = sliderFrame.parent.sliderMin or 0 | |
| 1997 local max = sliderFrame.parent.sliderMax or 1 | |
| 1998 local step | |
| 1999 if sliderFrame.fineStep then | |
| 2000 step = sliderFrame.parent.sliderStep or (max - min) / 100 | |
| 2001 else | |
| 2002 step = sliderFrame.parent.sliderBigStep or sliderFrame.parent.sliderStep or (max - min) / 100 | |
| 2003 end | |
| 2004 local value = (1 - slider:GetValue()) * (max - min) + min | |
| 2005 if step > 0 then | |
| 2006 value = math.floor((value - min) / step + 0.5) * step + min | |
| 2007 if value > max then | |
| 2008 value = max | |
| 2009 elseif value < min then | |
| 2010 value = min | |
| 2011 end | |
| 2012 end | |
| 2013 if value == sliderFrame.lastValue then | |
| 2014 return | |
| 2015 end | |
| 2016 sliderFrame.lastValue = value | |
| 2017 local text = sliderFrame.parent.sliderFunc(getArgs(sliderFrame.parent, 'sliderArg', 1, value)) | |
| 2018 if sliderFrame.parent.fromAceOptions then | |
| 2019 text = nil | |
| 2020 elseif type(text) == "string" or type(text) == "number" then | |
| 2021 sliderFrame.currentText:SetText(text) | |
| 2022 done = true | |
| 2023 end | |
| 2024 end | |
| 2025 if not done then | |
| 2026 local min = sliderFrame.parent.sliderMin or 0 | |
| 2027 local max = sliderFrame.parent.sliderMax or 1 | |
| 2028 local step | |
| 2029 if sliderFrame.fineStep then | |
| 2030 step = sliderFrame.parent.sliderStep or (max - min) / 100 | |
| 2031 else | |
| 2032 step = sliderFrame.parent.sliderBigStep or sliderFrame.parent.sliderStep or (max - min) / 100 | |
| 2033 end | |
| 2034 local value = (1 - slider:GetValue()) * (max - min) + min | |
| 2035 if step > 0 then | |
| 2036 value = math.floor((value - min) / step + 0.5) * step + min | |
| 2037 if value > max then | |
| 2038 value = max | |
| 2039 elseif value < min then | |
| 2040 value = min | |
| 2041 end | |
| 2042 end | |
| 2043 if sliderFrame.parent.sliderIsPercent then | |
| 2044 sliderFrame.currentText:SetText(string.format("%.0f%%", value * 100)) | |
| 2045 else | |
| 2046 if step < 0.1 then | |
| 2047 sliderFrame.currentText:SetText(string.format("%.2f", value)) | |
| 2048 elseif step < 1 then | |
| 2049 sliderFrame.currentText:SetText(string.format("%.1f", value)) | |
| 2050 else | |
| 2051 sliderFrame.currentText:SetText(string.format("%.0f", value)) | |
| 2052 end | |
| 2053 end | |
| 2054 end | |
| 2055 end) | |
| 2056 local function onEnter() | |
| 2057 StopCounting(self, sliderFrame.level) | |
| 2058 showGameTooltip(sliderFrame.parent) | |
| 2059 end | |
| 2060 local function onLeave() | |
| 2061 GameTooltip:Hide() | |
| 2062 end | |
| 2063 sliderFrame:SetScript("OnEnter", onEnter) | |
| 2064 sliderFrame:SetScript("OnLeave", function() | |
| 2065 GameTooltip:Hide() | |
| 2066 if changed then | |
| 2067 local parent = sliderFrame.parent | |
| 2068 local sliderFunc = parent.sliderFunc | |
| 2069 for i = 1, sliderFrame.level - 1 do | |
| 2070 Refresh(self, levels[i]) | |
| 2071 end | |
| 2072 local newParent | |
| 2073 for _,button in ipairs(levels[sliderFrame.level-1].buttons) do | |
| 2074 if button.sliderFunc == sliderFunc then | |
| 2075 newParent = button | |
| 2076 break | |
| 2077 end | |
| 2078 end | |
| 2079 if newParent then | |
| 2080 OpenSlider(self, newParent) | |
| 2081 else | |
| 2082 sliderFrame:Hide() | |
| 2083 end | |
| 2084 end | |
| 2085 end) | |
| 2086 editBox:SetScript("OnEnter", onEnter) | |
| 2087 editBox:SetScript("OnLeave", onLeave) | |
| 2088 slider:SetScript("OnMouseDown", function() | |
| 2089 sliderFrame.mouseDown = true | |
| 2090 GameTooltip:Hide() | |
| 2091 end) | |
| 2092 slider:SetScript("OnMouseUp", function() | |
| 2093 sliderFrame.mouseDown = false | |
| 2094 if changed--[[ and not inside]] then | |
| 2095 local parent = sliderFrame.parent | |
| 2096 local sliderFunc = parent.sliderFunc | |
| 2097 for i = 1, sliderFrame.level - 1 do | |
| 2098 Refresh(self, levels[i]) | |
| 2099 end | |
| 2100 local newParent | |
| 2101 for _,button in ipairs(levels[sliderFrame.level-1].buttons) do | |
| 2102 if button.sliderFunc == sliderFunc then | |
| 2103 newParent = button | |
| 2104 break | |
| 2105 end | |
| 2106 end | |
| 2107 if newParent then | |
| 2108 OpenSlider(self, newParent) | |
| 2109 else | |
| 2110 sliderFrame:Hide() | |
| 2111 end | |
| 2112 end | |
| 2113 if inside then | |
| 2114 showGameTooltip(sliderFrame.parent) | |
| 2115 end | |
| 2116 end) | |
| 2117 slider:SetScript("OnEnter", function() | |
| 2118 inside = true | |
| 2119 StopCounting(self, sliderFrame.level) | |
| 2120 showGameTooltip(sliderFrame.parent) | |
| 2121 end) | |
| 2122 slider:SetScript("OnLeave", function() | |
| 2123 inside = false | |
| 2124 GameTooltip:Hide() | |
| 2125 if changed and not sliderFrame.mouseDown then | |
| 2126 local parent = sliderFrame.parent | |
| 2127 local sliderFunc = parent.sliderFunc | |
| 2128 for i = 1, sliderFrame.level - 1 do | |
| 2129 Refresh(self, levels[i]) | |
| 2130 end | |
| 2131 local newParent | |
| 2132 for _,button in ipairs(levels[sliderFrame.level-1].buttons) do | |
| 2133 if button.sliderFunc == sliderFunc then | |
| 2134 newParent = button | |
| 2135 break | |
| 2136 end | |
| 2137 end | |
| 2138 if newParent then | |
| 2139 OpenSlider(self, newParent) | |
| 2140 else | |
| 2141 sliderFrame:Hide() | |
| 2142 end | |
| 2143 | |
| 2144 changed = false | |
| 2145 end | |
| 2146 end) | |
| 2147 sliderFrame:SetScript("OnMouseWheel", function(t, a1) | |
| 2148 local arg1 = a1 or arg1 | |
| 2149 local up = arg1 > 0 | |
| 2150 | |
| 2151 local min = sliderFrame.parent.sliderMin or 0 | |
| 2152 local max = sliderFrame.parent.sliderMax or 1 | |
| 2153 local step = sliderFrame.parent.sliderStep or (max - min) / 100 | |
| 2154 if step <= 0 then | |
| 2155 step = (max - min) / 100 | |
| 2156 end | |
| 2157 | |
| 2158 local value = (1 - slider:GetValue()) * (max - min) + min | |
| 2159 if up then | |
| 2160 value = value + step | |
| 2161 else | |
| 2162 value = value - step | |
| 2163 end | |
| 2164 if value > max then | |
| 2165 value = max | |
| 2166 elseif value < min then | |
| 2167 value = min | |
| 2168 end | |
| 2169 sliderFrame.fineStep = true | |
| 2170 if max<=min then | |
| 2171 slider:SetValue(0) | |
| 2172 else | |
| 2173 slider:SetValue(1 - (value - min) / (max - min)) | |
| 2174 end | |
| 2175 sliderFrame.fineStep = nil | |
| 2176 end) | |
| 2177 slider:SetScript("OnMouseWheel", sliderFrame:GetScript("OnMouseWheel")) | |
| 2178 editBox:SetScript("OnEnterPressed", function(t, a1) | |
| 2179 local value = editBox:GetNumber() | |
| 2180 | |
| 2181 if sliderFrame.parent.sliderIsPercent then | |
| 2182 value = value / 100 | |
| 2183 end | |
| 2184 | |
| 2185 local min = sliderFrame.parent.sliderMin or 0 | |
| 2186 local max = sliderFrame.parent.sliderMax or 1 | |
| 2187 | |
| 2188 if value > max then | |
| 2189 value = max | |
| 2190 elseif value < min then | |
| 2191 value = min | |
| 2192 end | |
| 2193 sliderFrame.fineStep = true | |
| 2194 if max <= min then | |
| 2195 slider:SetValue(0) | |
| 2196 else | |
| 2197 slider:SetValue(1 - (value - min) / (max - min)) | |
| 2198 end | |
| 2199 sliderFrame.fineStep = nil | |
| 2200 | |
| 2201 StartCounting(self, sliderFrame.level) | |
| 2202 end) | |
| 2203 editBox:SetScript("OnEscapePressed", function() | |
| 2204 self:Close(sliderFrame.level) | |
| 2205 StartCounting(self, sliderFrame.level) | |
| 2206 end) | |
| 2207 editBox:SetAutoFocus(false) | |
| 2208 end | |
| 2209 sliderFrame.parent = parent | |
| 2210 sliderFrame.level = parent.level.num + 1 | |
| 2211 sliderFrame.parentValue = parent.level.value | |
| 2212 sliderFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3) | |
| 2213 sliderFrame.slider:SetFrameLevel(sliderFrame:GetFrameLevel() + 1) | |
| 2214 sliderFrame.currentText:SetFrameLevel(sliderFrame:GetFrameLevel() + 1) | |
| 2215 sliderFrame.currentText:ClearFocus() | |
| 2216 sliderFrame.changing = true | |
| 2217 if not parent.sliderMin or not parent.sliderMax then | |
| 2218 return | |
| 2219 end | |
| 2220 | |
| 2221 if parent.arrow then | |
| 2222 -- parent.arrow:SetVertexColor(0.2, 0.6, 0) | |
| 2223 -- parent.arrow:SetHeight(24) | |
| 2224 -- parent.arrow:SetWidth(24) | |
| 2225 parent.selected = true | |
| 2226 parent.highlight:Show() | |
| 2227 end | |
| 2228 | |
| 2229 sliderFrame:SetClampedToScreen(false) | |
| 2230 if not parent.sliderValue then | |
| 2231 parent.sliderValue = (parent.sliderMin + parent.sliderMax) / 2 | |
| 2232 end | |
| 2233 if parent.sliderMax <= parent.sliderMin then | |
| 2234 sliderFrame.slider:SetValue(0) | |
| 2235 else | |
| 2236 sliderFrame.slider:SetValue(1 - (parent.sliderValue - parent.sliderMin) / (parent.sliderMax - parent.sliderMin)) | |
| 2237 end | |
| 2238 sliderFrame.changing = false | |
| 2239 sliderFrame.bottomText:SetText(parent.sliderMinText or "0") | |
| 2240 sliderFrame.topText:SetText(parent.sliderMaxText or "1") | |
| 2241 local text | |
| 2242 if parent.sliderFunc and not parent.fromAceOptions then | |
| 2243 text = parent.sliderFunc(getArgs(parent, 'sliderArg', 1, parent.sliderValue)) | |
| 2244 end | |
| 2245 if type(text) == "number" or type(text) == "string" then | |
| 2246 sliderFrame.currentText:SetText(text) | |
| 2247 elseif parent.sliderIsPercent then | |
| 2248 sliderFrame.currentText:SetText(string.format("%.0f%%", parent.sliderValue * 100)) | |
| 2249 else | |
| 2250 if parent.sliderStep < 0.1 then | |
| 2251 sliderFrame.currentText:SetText(string.format("%.2f", parent.sliderValue)) | |
| 2252 elseif parent.sliderStep < 1 then | |
| 2253 sliderFrame.currentText:SetText(string.format("%.1f", parent.sliderValue)) | |
| 2254 else | |
| 2255 sliderFrame.currentText:SetText(string.format("%.0f", parent.sliderValue)) | |
| 2256 end | |
| 2257 end | |
| 2258 | |
| 2259 | |
| 2260 sliderFrame.lastValue = parent.sliderValue | |
| 2261 | |
| 2262 local level = parent.level | |
| 2263 sliderFrame:Show() | |
| 2264 sliderFrame:ClearAllPoints() | |
| 2265 if level.lastDirection == "RIGHT" then | |
| 2266 if level.lastVDirection == "DOWN" then | |
| 2267 sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) | |
| 2268 else | |
| 2269 sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) | |
| 2270 end | |
| 2271 else | |
| 2272 if level.lastVDirection == "DOWN" then | |
| 2273 sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) | |
| 2274 else | |
| 2275 sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) | |
| 2276 end | |
| 2277 end | |
| 2278 local dirty | |
| 2279 if level.lastDirection == "RIGHT" then | |
| 2280 if sliderFrame:GetRight() > GetScreenWidth() then | |
| 2281 level.lastDirection = "LEFT" | |
| 2282 dirty = true | |
| 2283 end | |
| 2284 elseif sliderFrame:GetLeft() < 0 then | |
| 2285 level.lastDirection = "RIGHT" | |
| 2286 dirty = true | |
| 2287 end | |
| 2288 if level.lastVDirection == "DOWN" then | |
| 2289 if sliderFrame:GetBottom() < 0 then | |
| 2290 level.lastVDirection = "UP" | |
| 2291 dirty = true | |
| 2292 end | |
| 2293 elseif sliderFrame:GetTop() > GetScreenWidth() then | |
| 2294 level.lastVDirection = "DOWN" | |
| 2295 dirty = true | |
| 2296 end | |
| 2297 if dirty then | |
| 2298 sliderFrame:ClearAllPoints() | |
| 2299 if level.lastDirection == "RIGHT" then | |
| 2300 if level.lastVDirection == "DOWN" then | |
| 2301 sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) | |
| 2302 else | |
| 2303 sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) | |
| 2304 end | |
| 2305 else | |
| 2306 if level.lastVDirection == "DOWN" then | |
| 2307 sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) | |
| 2308 else | |
| 2309 sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) | |
| 2310 end | |
| 2311 end | |
| 2312 end | |
| 2313 local left, bottom = sliderFrame:GetLeft(), sliderFrame:GetBottom() | |
| 2314 sliderFrame:ClearAllPoints() | |
| 2315 sliderFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) | |
| 2316 if mod(level.num, 5) == 0 then | |
| 2317 local left, bottom = level:GetLeft(), level:GetBottom() | |
| 2318 level:ClearAllPoints() | |
| 2319 level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) | |
| 2320 end | |
| 2321 sliderFrame:SetClampedToScreen(true) | |
| 2322 end | |
| 2323 | |
| 2324 function OpenEditBox(self, parent) | |
| 2325 if not editBoxFrame then | |
| 2326 editBoxFrame = CreateFrame("Frame", nil, nil) | |
| 2327 editBoxFrame:SetWidth(200) | |
| 2328 editBoxFrame:SetHeight(40) | |
| 2329 editBoxFrame:SetScale(UIParent:GetScale()) | |
| 2330 editBoxFrame:SetBackdrop(tmp( | |
| 2331 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", | |
| 2332 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", | |
| 2333 'tile', true, | |
| 2334 'insets', tmp2( | |
| 2335 'left', 5, | |
| 2336 'right', 5, | |
| 2337 'top', 5, | |
| 2338 'bottom', 5 | |
| 2339 ), | |
| 2340 'tileSize', 16, | |
| 2341 'edgeSize', 16 | |
| 2342 )) | |
| 2343 editBoxFrame:SetFrameStrata("FULLSCREEN_DIALOG") | |
| 2344 if editBoxFrame.SetTopLevel then | |
| 2345 editBoxFrame:SetTopLevel(true) | |
| 2346 end | |
| 2347 editBoxFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) | |
| 2348 editBoxFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) | |
| 2349 editBoxFrame:EnableMouse(true) | |
| 2350 editBoxFrame:EnableMouseWheel(true) | |
| 2351 editBoxFrame:Hide() | |
| 2352 editBoxFrame:SetPoint("CENTER", UIParent, "CENTER") | |
| 2353 | |
| 2354 local editBox = CreateFrame("EditBox", nil, editBoxFrame) | |
| 2355 editBoxFrame.editBox = editBox | |
| 2356 editBox:SetFontObject(ChatFontNormal) | |
| 2357 editBox:SetWidth(160) | |
| 2358 editBox:SetHeight(13) | |
| 2359 editBox:SetPoint("CENTER", editBoxFrame, "CENTER", 0, 0) | |
| 2360 | |
| 2361 local left = editBox:CreateTexture(nil, "BACKGROUND") | |
| 2362 left:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Left") | |
| 2363 left:SetTexCoord(0, 100 / 256, 0, 1) | |
| 2364 left:SetWidth(100) | |
| 2365 left:SetHeight(32) | |
| 2366 left:SetPoint("LEFT", editBox, "LEFT", -10, 0) | |
| 2367 local right = editBox:CreateTexture(nil, "BACKGROUND") | |
| 2368 right:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Right") | |
| 2369 right:SetTexCoord(156/256, 1, 0, 1) | |
| 2370 right:SetWidth(100) | |
| 2371 right:SetHeight(32) | |
| 2372 right:SetPoint("RIGHT", editBox, "RIGHT", 10, 0) | |
| 2373 | |
| 2374 editBox:SetScript("OnEnterPressed", function() | |
| 2375 if editBoxFrame.parent and editBoxFrame.parent.editBoxValidateFunc then | |
| 2376 local t = editBox.realText or editBox:GetText() or "" | |
| 2377 local result = editBoxFrame.parent.editBoxValidateFunc(getArgs(editBoxFrame.parent, 'editBoxValidateArg', 1, t)) | |
| 2378 if not result then | |
| 2379 UIErrorsFrame:AddMessage(VALIDATION_ERROR, 1, 0, 0) | |
| 2380 return | |
| 2381 end | |
| 2382 end | |
| 2383 if editBoxFrame.parent and editBoxFrame.parent.editBoxFunc then | |
| 2384 local t | |
| 2385 if editBox.realText ~= "NONE" then | |
| 2386 t = editBox.realText or editBox:GetText() or "" | |
| 2387 end | |
| 2388 editBoxFrame.parent.editBoxFunc(getArgs(editBoxFrame.parent, 'editBoxArg', 1, t)) | |
| 2389 end | |
| 2390 self:Close(editBoxFrame.level) | |
| 2391 for i = 1, editBoxFrame.level - 1 do | |
| 2392 Refresh(self, levels[i]) | |
| 2393 end | |
| 2394 StartCounting(self, editBoxFrame.level-1) | |
| 2395 end) | |
| 2396 editBox:SetScript("OnEscapePressed", function() | |
| 2397 self:Close(editBoxFrame.level) | |
| 2398 StartCounting(self, editBoxFrame.level-1) | |
| 2399 end) | |
| 2400 editBox:SetScript("OnReceiveDrag", function(this) | |
| 2401 if GetCursorInfo then | |
| 2402 local type, alpha, bravo = GetCursorInfo() | |
| 2403 local text | |
| 2404 if type == "spell" then | |
| 2405 text = GetSpellName(alpha, bravo) | |
| 2406 elseif type == "item" then | |
| 2407 text = bravo | |
| 2408 end | |
| 2409 if not text then | |
| 2410 return | |
| 2411 end | |
| 2412 ClearCursor() | |
| 2413 editBox:SetText(text) | |
| 2414 end | |
| 2415 end) | |
| 2416 local changing = false | |
| 2417 local skipNext = false | |
| 2418 | |
| 2419 function editBox:SpecialSetText(text) | |
| 2420 local oldText = editBox:GetText() or "" | |
| 2421 if not text then | |
| 2422 text = "" | |
| 2423 end | |
| 2424 if text ~= oldText then | |
| 2425 changing = true | |
| 2426 self:SetText(tostring(text)) | |
| 2427 changing = false | |
| 2428 skipNext = true | |
| 2429 end | |
| 2430 end | |
| 2431 | |
| 2432 editBox:SetScript("OnTextChanged", function() | |
| 2433 if skipNext then | |
| 2434 skipNext = false | |
| 2435 elseif not changing and editBoxFrame.parent and editBoxFrame.parent.editBoxChangeFunc then | |
| 2436 local t | |
| 2437 if editBox.realText ~= "NONE" then | |
| 2438 t = editBox.realText or editBox:GetText() or "" | |
| 2439 end | |
| 2440 local text = editBoxFrame.parent.editBoxChangeFunc(getArgs(editBoxFrame.parent, 'editBoxChangeArg', 1, t)) | |
| 2441 if text then | |
| 2442 editBox:SpecialSetText(text) | |
| 2443 end | |
| 2444 end | |
| 2445 end) | |
| 2446 editBoxFrame:SetScript("OnEnter", function() | |
| 2447 StopCounting(self, editBoxFrame.level) | |
| 2448 showGameTooltip(editBoxFrame.parent) | |
| 2449 end) | |
| 2450 editBoxFrame:SetScript("OnLeave", function() | |
| 2451 GameTooltip:Hide() | |
| 2452 end) | |
| 2453 editBox:SetScript("OnEnter", function() | |
| 2454 StopCounting(self, editBoxFrame.level) | |
| 2455 showGameTooltip(editBoxFrame.parent) | |
| 2456 end) | |
| 2457 editBox:SetScript("OnLeave", function() | |
| 2458 GameTooltip:Hide() | |
| 2459 end) | |
| 2460 editBoxFrame:SetScript("OnKeyDown", function(this, a1) | |
| 2461 if not editBox.keybinding then | |
| 2462 return | |
| 2463 end | |
| 2464 local arg1 = a1 or arg1 | |
| 2465 local screenshotKey = GetBindingKey("SCREENSHOT") | |
| 2466 if screenshotKey and arg1 == screenshotKey then | |
| 2467 Screenshot() | |
| 2468 return | |
| 2469 end | |
| 2470 | |
| 2471 if arg1 == "LeftButton" then | |
| 2472 arg1 = "BUTTON1" | |
| 2473 elseif arg1 == "RightButton" then | |
| 2474 arg1 = "BUTTON2" | |
| 2475 elseif arg1 == "MiddleButton" then | |
| 2476 arg1 = "BUTTON3" | |
| 2477 elseif arg1 == "Button4" then | |
| 2478 arg1 = "BUTTON4" | |
| 2479 elseif arg1 == "Button5" then | |
| 2480 arg1 = "BUTTON5" | |
| 2481 end | |
| 2482 if arg1 == "UNKNOWN" then | |
| 2483 return | |
| 2484 elseif arg1 == "SHIFT" or arg1 == "CTRL" or arg1 == "ALT" then | |
| 2485 return | |
| 2486 elseif arg1 == "ENTER" then | |
| 2487 if editBox.keybindingOnly and not editBox.keybindingOnly[editBox.realText] then | |
| 2488 return editBox:GetScript("OnEscapePressed")() | |
| 2489 elseif editBox.keybindingExcept and editBox.keybindingExcept[editBox.realText] then | |
| 2490 return editBox:GetScript("OnEscapePressed")() | |
| 2491 else | |
| 2492 return editBox:GetScript("OnEnterPressed")() | |
| 2493 end | |
| 2494 elseif arg1 == "ESCAPE" then | |
| 2495 if editBox.realText == "NONE" then | |
| 2496 return editBox:GetScript("OnEscapePressed")() | |
| 2497 else | |
| 2498 editBox:SpecialSetText(NONE or "NONE") | |
| 2499 editBox.realText = "NONE" | |
| 2500 return | |
| 2501 end | |
| 2502 elseif editBox.keybindingOnly and not editBox.keybindingOnly[arg1] then | |
| 2503 return | |
| 2504 elseif editBox.keybindingExcept and editBox.keybindingExcept[arg1] then | |
| 2505 return | |
| 2506 end | |
| 2507 local s = GetBindingText(arg1, "KEY_") | |
| 2508 if s == "BUTTON1" then | |
| 2509 s = KEY_BUTTON1 | |
| 2510 elseif s == "BUTTON2" then | |
| 2511 s = KEY_BUTTON2 | |
| 2512 end | |
| 2513 local real = arg1 | |
| 2514 if IsShiftKeyDown() then | |
| 2515 s = "Shift-" .. s | |
| 2516 real = "SHIFT-" .. real | |
| 2517 end | |
| 2518 if IsControlKeyDown() then | |
| 2519 s = "Ctrl-" .. s | |
| 2520 real = "CTRL-" .. real | |
| 2521 end | |
| 2522 if IsAltKeyDown() then | |
| 2523 s = "Alt-" .. s | |
| 2524 real = "ALT-" .. real | |
| 2525 end | |
| 2526 if editBox:GetText() ~= s then | |
| 2527 editBox:SpecialSetText("-") | |
| 2528 editBox:SpecialSetText(s) | |
| 2529 editBox.realText = real | |
| 2530 return editBox:GetScript("OnTextChanged")() | |
| 2531 end | |
| 2532 end) | |
| 2533 editBoxFrame:SetScript("OnMouseDown", editBoxFrame:GetScript("OnKeyDown")) | |
| 2534 editBox:SetScript("OnMouseDown", function(this, ...) | |
| 2535 if GetCursorInfo and (CursorHasItem() or CursorHasSpell()) then | |
| 2536 return editBox:GetScript("OnReceiveDrag")(this, ...) | |
| 2537 end | |
| 2538 return editBoxFrame:GetScript("OnKeyDown")(this, ...) | |
| 2539 end) | |
| 2540 editBoxFrame:SetScript("OnMouseWheel", function(t, a1) | |
| 2541 local arg1 = a1 or arg1 | |
| 2542 local up = arg1 > 0 | |
| 2543 arg1 = up and "MOUSEWHEELUP" or "MOUSEWHEELDOWN" | |
| 2544 return editBoxFrame:GetScript("OnKeyDown")(t or this, arg1) | |
| 2545 end) | |
| 2546 editBox:SetScript("OnMouseWheel", editBoxFrame:GetScript("OnMouseWheel")) | |
| 2547 end | |
| 2548 editBoxFrame.parent = parent | |
| 2549 editBoxFrame.level = parent.level.num + 1 | |
| 2550 editBoxFrame.parentValue = parent.level.value | |
| 2551 editBoxFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3) | |
| 2552 editBoxFrame.editBox:SetFrameLevel(editBoxFrame:GetFrameLevel() + 1) | |
| 2553 editBoxFrame.editBox.realText = nil | |
| 2554 editBoxFrame:SetClampedToScreen(false) | |
| 2555 | |
| 2556 editBoxFrame.editBox:SpecialSetText("") | |
| 2557 if parent.editBoxIsKeybinding then | |
| 2558 local s = parent.editBoxText | |
| 2559 if s == "" then | |
| 2560 s = "NONE" | |
| 2561 end | |
| 2562 editBoxFrame.editBox.realText = s | |
| 2563 if s and s ~= "NONE" then | |
| 2564 local alpha,bravo = s:match("^(.+)%-(.+)$") | |
| 2565 if not bravo then | |
| 2566 alpha = nil | |
| 2567 bravo = s | |
| 2568 end | |
| 2569 bravo = GetBindingText(bravo, "KEY_") | |
| 2570 if alpha then | |
| 2571 editBoxFrame.editBox:SpecialSetText(alpha:upper() .. "-" .. bravo) | |
| 2572 else | |
| 2573 editBoxFrame.editBox:SpecialSetText(bravo) | |
| 2574 end | |
| 2575 else | |
| 2576 editBoxFrame.editBox:SpecialSetText(NONE or "NONE") | |
| 2577 end | |
| 2578 else | |
| 2579 editBoxFrame.editBox:SpecialSetText(parent.editBoxText) | |
| 2580 end | |
| 2581 | |
| 2582 editBoxFrame.editBox.keybinding = parent.editBoxIsKeybinding | |
| 2583 editBoxFrame.editBox.keybindingOnly = parent.editBoxKeybindingOnly | |
| 2584 editBoxFrame.editBox.keybindingExcept = parent.editBoxKeybindingExcept | |
| 2585 editBoxFrame.editBox:EnableKeyboard(not parent.editBoxIsKeybinding) | |
| 2586 editBoxFrame:EnableKeyboard(parent.editBoxIsKeybinding) | |
| 2587 | |
| 2588 if parent.arrow then | |
| 2589 -- parent.arrow:SetVertexColor(0.2, 0.6, 0) | |
| 2590 -- parent.arrow:SetHeight(24) | |
| 2591 -- parent.arrow:SetWidth(24) | |
| 2592 parent.selected = true | |
| 2593 parent.highlight:Show() | |
| 2594 end | |
| 2595 | |
| 2596 local level = parent.level | |
| 2597 editBoxFrame:Show() | |
| 2598 editBoxFrame:ClearAllPoints() | |
| 2599 if level.lastDirection == "RIGHT" then | |
| 2600 if level.lastVDirection == "DOWN" then | |
| 2601 editBoxFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) | |
| 2602 else | |
| 2603 editBoxFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) | |
| 2604 end | |
| 2605 else | |
| 2606 if level.lastVDirection == "DOWN" then | |
| 2607 editBoxFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) | |
| 2608 else | |
| 2609 editBoxFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) | |
| 2610 end | |
| 2611 end | |
| 2612 local dirty | |
| 2613 if level.lastDirection == "RIGHT" then | |
| 2614 if editBoxFrame:GetRight() > GetScreenWidth() then | |
| 2615 level.lastDirection = "LEFT" | |
| 2616 dirty = true | |
| 2617 end | |
| 2618 elseif editBoxFrame:GetLeft() < 0 then | |
| 2619 level.lastDirection = "RIGHT" | |
| 2620 dirty = true | |
| 2621 end | |
| 2622 if level.lastVDirection == "DOWN" then | |
| 2623 if editBoxFrame:GetBottom() < 0 then | |
| 2624 level.lastVDirection = "UP" | |
| 2625 dirty = true | |
| 2626 end | |
| 2627 elseif editBoxFrame:GetTop() > GetScreenWidth() then | |
| 2628 level.lastVDirection = "DOWN" | |
| 2629 dirty = true | |
| 2630 end | |
| 2631 if dirty then | |
| 2632 editBoxFrame:ClearAllPoints() | |
| 2633 if level.lastDirection == "RIGHT" then | |
| 2634 if level.lastVDirection == "DOWN" then | |
| 2635 editBoxFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) | |
| 2636 else | |
| 2637 editBoxFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) | |
| 2638 end | |
| 2639 else | |
| 2640 if level.lastVDirection == "DOWN" then | |
| 2641 editBoxFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) | |
| 2642 else | |
| 2643 editBoxFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) | |
| 2644 end | |
| 2645 end | |
| 2646 end | |
| 2647 local left, bottom = editBoxFrame:GetLeft(), editBoxFrame:GetBottom() | |
| 2648 editBoxFrame:ClearAllPoints() | |
| 2649 editBoxFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) | |
| 2650 if mod(level.num, 5) == 0 then | |
| 2651 local left, bottom = level:GetLeft(), level:GetBottom() | |
| 2652 level:ClearAllPoints() | |
| 2653 level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) | |
| 2654 end | |
| 2655 editBoxFrame:SetClampedToScreen(true) | |
| 2656 end | |
| 2657 | |
| 2658 function Dewdrop:EncodeKeybinding(text) | |
| 2659 if text == nil or text == "NONE" then | |
| 2660 return nil | |
| 2661 end | |
| 2662 text = tostring(text):upper() | |
| 2663 local shift, ctrl, alt | |
| 2664 local modifier | |
| 2665 while true do | |
| 2666 if text == "-" then | |
| 2667 break | |
| 2668 end | |
| 2669 modifier, text = strsplit('-', text, 2) | |
| 2670 if text then | |
| 2671 if modifier ~= "SHIFT" and modifier ~= "CTRL" and modifier ~= "ALT" then | |
| 2672 return false | |
| 2673 end | |
| 2674 if modifier == "SHIFT" then | |
| 2675 if shift then | |
| 2676 return false | |
| 2677 end | |
| 2678 shift = true | |
| 2679 end | |
| 2680 if modifier == "CTRL" then | |
| 2681 if ctrl then | |
| 2682 return false | |
| 2683 end | |
| 2684 ctrl = true | |
| 2685 end | |
| 2686 if modifier == "ALT" then | |
| 2687 if alt then | |
| 2688 return false | |
| 2689 end | |
| 2690 alt = true | |
| 2691 end | |
| 2692 else | |
| 2693 text = modifier | |
| 2694 break | |
| 2695 end | |
| 2696 end | |
| 2697 if not text:find("^F%d+$") and text ~= "CAPSLOCK" and text:len() ~= 1 and (text:len() == 0 or text:byte() < 128 or text:len() > 4) and not _G["KEY_" .. text] and text ~= "BUTTON1" and text ~= "BUTTON2" then | |
| 2698 return false | |
| 2699 end | |
| 2700 local s = GetBindingText(text, "KEY_") | |
| 2701 if s == "BUTTON1" then | |
| 2702 s = KEY_BUTTON1 | |
| 2703 elseif s == "BUTTON2" then | |
| 2704 s = KEY_BUTTON2 | |
| 2705 end | |
| 2706 if shift then | |
| 2707 s = "Shift-" .. s | |
| 2708 end | |
| 2709 if ctrl then | |
| 2710 s = "Ctrl-" .. s | |
| 2711 end | |
| 2712 if alt then | |
| 2713 s = "Alt-" .. s | |
| 2714 end | |
| 2715 return s | |
| 2716 end | |
| 2717 | |
| 2718 function Dewdrop:IsOpen(parent) | |
| 2719 self:argCheck(parent, 2, "table", "string", "nil") | |
| 2720 return levels[1] and levels[1]:IsShown() and (not parent or parent == levels[1].parent or parent == levels[1]:GetParent()) | |
| 2721 end | |
| 2722 | |
| 2723 function Dewdrop:GetOpenedParent() | |
| 2724 return (levels[1] and levels[1]:IsShown()) and (levels[1].parent or levels[1]:GetParent()) | |
| 2725 end | |
| 2726 | |
| 2727 function Open(self, parent, func, level, value, point, relativePoint, cursorX, cursorY) | |
| 2728 self:Close(level) | |
| 2729 if DewdropLib then | |
| 2730 local d = DewdropLib:GetInstance('1.0') | |
| 2731 local ret, val = pcall(d, IsOpen, d) | |
| 2732 if ret and val then | |
| 2733 DewdropLib:GetInstance('1.0'):Close() | |
| 2734 end | |
| 2735 end | |
| 2736 if type(parent) == "table" then | |
| 2737 parent:GetCenter() | |
| 2738 end | |
| 2739 local frame = AcquireLevel(self, level) | |
| 2740 if level == 1 then | |
| 2741 frame.lastDirection = "RIGHT" | |
| 2742 frame.lastVDirection = "DOWN" | |
| 2743 else | |
| 2744 frame.lastDirection = levels[level - 1].lastDirection | |
| 2745 frame.lastVDirection = levels[level - 1].lastVDirection | |
| 2746 end | |
| 2747 frame:SetFrameStrata("FULLSCREEN_DIALOG") | |
| 2748 frame:ClearAllPoints() | |
| 2749 frame.parent = parent | |
| 2750 frame:SetPoint("LEFT", UIParent, "RIGHT", 10000, 0) | |
| 2751 frame:Show() | |
| 2752 if level == 1 then | |
| 2753 baseFunc = func | |
| 2754 end | |
| 2755 levels[level].value = value | |
| 2756 -- levels[level].parentText = parent.text and parent.text:GetText() or nil | |
| 2757 -- levels[level].parentTooltipTitle = parent.tooltipTitle | |
| 2758 -- levels[level].parentTooltipText = parent.tooltipText | |
| 2759 -- levels[level].parentTooltipFunc = parent.tooltipFunc | |
| 2760 if type(parent) == "table" and parent.arrow then | |
| 2761 -- parent.arrow:SetVertexColor(0.2, 0.6, 0) | |
| 2762 -- parent.arrow:SetHeight(24) | |
| 2763 -- parent.arrow:SetWidth(24) | |
| 2764 parent.selected = true | |
| 2765 parent.highlight:Show() | |
| 2766 end | |
| 2767 relativePoint = relativePoint or point | |
| 2768 Refresh(self, levels[level]) | |
| 2769 if point or (cursorX and cursorY) then | |
| 2770 frame:ClearAllPoints() | |
| 2771 if cursorX and cursorY then | |
| 2772 local curX, curY = GetScaledCursorPosition() | |
| 2773 if curY < GetScreenHeight() / 2 then | |
| 2774 point, relativePoint = "BOTTOM", "BOTTOM" | |
| 2775 else | |
| 2776 point, relativePoint = "TOP", "TOP" | |
| 2777 end | |
| 2778 if curX < GetScreenWidth() / 2 then | |
| 2779 point, relativePoint = point .. "LEFT", relativePoint .. "RIGHT" | |
| 2780 else | |
| 2781 point, relativePoint = point .. "RIGHT", relativePoint .. "LEFT" | |
| 2782 end | |
| 2783 end | |
| 2784 frame:SetPoint(point, type(parent) == "table" and parent or UIParent, relativePoint) | |
| 2785 if cursorX and cursorY then | |
| 2786 local left = frame:GetLeft() | |
| 2787 local width = frame:GetWidth() | |
| 2788 local bottom = frame:GetBottom() | |
| 2789 local height = frame:GetHeight() | |
| 2790 local curX, curY = GetScaledCursorPosition() | |
| 2791 frame:ClearAllPoints() | |
| 2792 relativePoint = relativePoint or point | |
| 2793 if point == "BOTTOM" or point == "TOP" then | |
| 2794 if curX < GetScreenWidth() / 2 then | |
| 2795 point = point .. "LEFT" | |
| 2796 else | |
| 2797 point = point .. "RIGHT" | |
| 2798 end | |
| 2799 elseif point == "CENTER" then | |
| 2800 if curX < GetScreenWidth() / 2 then | |
| 2801 point = "LEFT" | |
| 2802 else | |
| 2803 point = "RIGHT" | |
| 2804 end | |
| 2805 end | |
| 2806 local xOffset, yOffset = 0, 0 | |
| 2807 if curY > GetScreenHeight() / 2 then | |
| 2808 yOffset = -height | |
| 2809 end | |
| 2810 if curX > GetScreenWidth() / 2 then | |
| 2811 xOffset = -width | |
| 2812 end | |
| 2813 frame:SetPoint(point, type(parent) == "table" and parent or UIParent, relativePoint, curX - left + xOffset, curY - bottom + yOffset) | |
| 2814 if level == 1 then | |
| 2815 frame.lastDirection = "RIGHT" | |
| 2816 end | |
| 2817 elseif cursorX then | |
| 2818 local left = frame:GetLeft() | |
| 2819 local width = frame:GetWidth() | |
| 2820 local curX, curY = GetScaledCursorPosition() | |
| 2821 frame:ClearAllPoints() | |
| 2822 relativePoint = relativePoint or point | |
| 2823 if point == "BOTTOM" or point == "TOP" then | |
| 2824 if curX < GetScreenWidth() / 2 then | |
| 2825 point = point .. "LEFT" | |
| 2826 else | |
| 2827 point = point .. "RIGHT" | |
| 2828 end | |
| 2829 elseif point == "CENTER" then | |
| 2830 if curX < GetScreenWidth() / 2 then | |
| 2831 point = "LEFT" | |
| 2832 else | |
| 2833 point = "RIGHT" | |
| 2834 end | |
| 2835 end | |
| 2836 frame:SetPoint(point, type(parent) == "table" and parent or UIParent, relativePoint, curX - left - width / 2, 0) | |
| 2837 if level == 1 then | |
| 2838 frame.lastDirection = "RIGHT" | |
| 2839 end | |
| 2840 elseif cursorY then | |
| 2841 local bottom = frame:GetBottom() | |
| 2842 local height = frame:GetHeight() | |
| 2843 local curX, curY = GetScaledCursorPosition() | |
| 2844 frame:ClearAllPoints() | |
| 2845 relativePoint = relativePoint or point | |
| 2846 if point == "LEFT" or point == "RIGHT" then | |
| 2847 if curX < GetScreenHeight() / 2 then | |
| 2848 point = point .. "BOTTOM" | |
| 2849 else | |
| 2850 point = point .. "TOP" | |
| 2851 end | |
| 2852 elseif point == "CENTER" then | |
| 2853 if curX < GetScreenHeight() / 2 then | |
| 2854 point = "BOTTOM" | |
| 2855 else | |
| 2856 point = "TOP" | |
| 2857 end | |
| 2858 end | |
| 2859 frame:SetPoint(point, type(parent) == "table" and parent or UIParent, relativePoint, 0, curY - bottom - height / 2) | |
| 2860 if level == 1 then | |
| 2861 frame.lastDirection = "DOWN" | |
| 2862 end | |
| 2863 end | |
| 2864 if (strsub(point, 1, 3) ~= strsub(relativePoint, 1, 3)) then | |
| 2865 if frame:GetBottom() < 0 then | |
| 2866 local point, parent, relativePoint, x, y = frame:GetPoint(1) | |
| 2867 local change = GetScreenHeight() - frame:GetTop() | |
| 2868 local otherChange = -frame:GetBottom() | |
| 2869 if otherChange < change then | |
| 2870 change = otherChange | |
| 2871 end | |
| 2872 frame:SetPoint(point, parent, relativePoint, x, y + change) | |
| 2873 elseif frame:GetTop() > GetScreenHeight() then | |
| 2874 local point, parent, relativePoint, x, y = frame:GetPoint(1) | |
| 2875 local change = GetScreenHeight() - frame:GetTop() | |
| 2876 local otherChange = -frame:GetBottom() | |
| 2877 if otherChange < change then | |
| 2878 change = otherChange | |
| 2879 end | |
| 2880 frame:SetPoint(point, parent, relativePoint, x, y + change) | |
| 2881 end | |
| 2882 end | |
| 2883 end | |
| 2884 CheckDualMonitor(self, frame) | |
| 2885 frame:SetClampedToScreen(true) | |
| 2886 frame:SetClampedToScreen(false) | |
| 2887 StartCounting(self, level) | |
| 2888 end | |
| 2889 | |
| 2890 function Dewdrop:IsRegistered(parent) | |
| 2891 self:argCheck(parent, 2, "table", "string") | |
| 2892 return not not self.registry[parent] | |
| 2893 end | |
| 2894 | |
| 2895 function Dewdrop:Register(parent, ...) | |
| 2896 self:argCheck(parent, 2, "table", "string") | |
| 2897 if self.registry[parent] then | |
| 2898 self:Unregister(parent) | |
| 2899 end | |
| 2900 local info = new(...) | |
| 2901 if type(info.children) == "table" then | |
| 2902 local err, position = validateOptions(info.children) | |
| 2903 | |
| 2904 if err then | |
| 2905 if position then | |
| 2906 Dewdrop:error(position .. ": " .. err) | |
| 2907 else | |
| 2908 Dewdrop:error(err) | |
| 2909 end | |
| 2910 end | |
| 2911 end | |
| 2912 self.registry[parent] = info | |
| 2913 if not info.dontHook and not self.onceRegistered[parent] and type(parent) == "table" then | |
| 2914 if parent:HasScript("OnMouseUp") then | |
| 2915 local script = parent:GetScript("OnMouseUp") | |
| 2916 parent:SetScript("OnMouseUp", function(this, ...) | |
| 2917 if script then | |
| 2918 script(this, ...) | |
| 2919 end | |
| 2920 if arg1 == "RightButton" and self.registry[parent] then | |
| 2921 if self:IsOpen(parent) then | |
| 2922 self:Close() | |
| 2923 else | |
| 2924 self:Open(parent) | |
| 2925 end | |
| 2926 end | |
| 2927 end) | |
| 2928 end | |
| 2929 if parent:HasScript("OnMouseDown") then | |
| 2930 local script = parent:GetScript("OnMouseDown") | |
| 2931 parent:SetScript("OnMouseDown", function(this, ...) | |
| 2932 if script then | |
| 2933 script(this, ...) | |
| 2934 end | |
| 2935 if self.registry[parent] then | |
| 2936 self:Close() | |
| 2937 end | |
| 2938 end) | |
| 2939 end | |
| 2940 end | |
| 2941 self.onceRegistered[parent] = true | |
| 2942 end | |
| 2943 | |
| 2944 function Dewdrop:Unregister(parent) | |
| 2945 self:argCheck(parent, 2, "table", "string") | |
| 2946 self.registry[parent] = nil | |
| 2947 end | |
| 2948 | |
| 2949 function Dewdrop:Open(parent, ...) | |
| 2950 self:argCheck(parent, 2, "table", "string") | |
| 2951 local info | |
| 2952 local k1 = ... | |
| 2953 if type(k1) == "table" and k1[0] and k1.IsFrameType and self.registry[k1] then | |
| 2954 info = tmp(select(2, ...)) | |
| 2955 for k,v in pairs(self.registry[k1]) do | |
| 2956 if info[k] == nil then | |
| 2957 info[k] = v | |
| 2958 end | |
| 2959 end | |
| 2960 else | |
| 2961 info = tmp(...) | |
| 2962 if self.registry[parent] then | |
| 2963 for k,v in pairs(self.registry[parent]) do | |
| 2964 if info[k] == nil then | |
| 2965 info[k] = v | |
| 2966 end | |
| 2967 end | |
| 2968 end | |
| 2969 end | |
| 2970 local point = info.point | |
| 2971 local relativePoint = info.relativePoint | |
| 2972 local cursorX = info.cursorX | |
| 2973 local cursorY = info.cursorY | |
| 2974 if type(point) == "function" then | |
| 2975 local b | |
| 2976 point, b = point(parent) | |
| 2977 if b then | |
| 2978 relativePoint = b | |
| 2979 end | |
| 2980 end | |
| 2981 if type(relativePoint) == "function" then | |
| 2982 relativePoint = relativePoint(parent) | |
| 2983 end | |
| 2984 Open(self, parent, info.children, 1, nil, point, relativePoint, cursorX, cursorY) | |
| 2985 end | |
| 2986 | |
| 2987 function Clear(self, level) | |
| 2988 if level then | |
| 2989 if level.buttons then | |
| 2990 for i = #level.buttons, 1, -1 do | |
| 2991 ReleaseButton(self, level, i) | |
| 2992 end | |
| 2993 end | |
| 2994 end | |
| 2995 end | |
| 2996 | |
| 2997 function Dewdrop:Close(level) | |
| 2998 if DropDownList1:IsShown() then | |
| 2999 DropDownList1:Hide() | |
| 3000 end | |
| 3001 if DewdropLib then | |
| 3002 local d = DewdropLib:GetInstance('1.0') | |
| 3003 local ret, val = pcall(d, IsOpen, d) | |
| 3004 if ret and val then | |
| 3005 DewdropLib:GetInstance('1.0'):Close() | |
| 3006 end | |
| 3007 end | |
| 3008 self:argCheck(level, 2, "number", "nil") | |
| 3009 if not level then | |
| 3010 level = 1 | |
| 3011 end | |
| 3012 if level == 1 and levels[level] then | |
| 3013 levels[level].parented = false | |
| 3014 end | |
| 3015 if level > 1 and levels[level-1].buttons then | |
| 3016 local buttons = levels[level-1].buttons | |
| 3017 for _,button in ipairs(buttons) do | |
| 3018 -- button.arrow:SetWidth(16) | |
| 3019 -- button.arrow:SetHeight(16) | |
| 3020 button.selected = nil | |
| 3021 button.highlight:Hide() | |
| 3022 -- button.arrow:SetVertexColor(1, 1, 1) | |
| 3023 end | |
| 3024 end | |
| 3025 if sliderFrame and sliderFrame.level >= level then | |
| 3026 sliderFrame:Hide() | |
| 3027 end | |
| 3028 if editBoxFrame and editBoxFrame.level >= level then | |
| 3029 editBoxFrame:Hide() | |
| 3030 end | |
| 3031 for i = level, #levels do | |
| 3032 Clear(self, levels[level]) | |
| 3033 levels[i]:Hide() | |
| 3034 levels[i]:ClearAllPoints() | |
| 3035 levels[i]:SetPoint("CENTER", UIParent, "CENTER") | |
| 3036 levels[i].value = nil | |
| 3037 end | |
| 3038 end | |
| 3039 | |
| 3040 function Dewdrop:AddSeparator(level) | |
| 3041 level = levels[level or currentLevel] | |
| 3042 if not level or not level.buttons then return; end | |
| 3043 | |
| 3044 local prevbutton = level.buttons[#level.buttons] | |
| 3045 if not prevbutton then return; end | |
| 3046 | |
| 3047 if prevbutton.disabled and prevbutton.text:GetText() == "" then | |
| 3048 return | |
| 3049 end | |
| 3050 self:AddLine("text", "", "disabled", true) | |
| 3051 end | |
| 3052 | |
| 3053 function Dewdrop:AddLine(...) | |
| 3054 local info = tmp(...) | |
| 3055 local level = info.level or currentLevel | |
| 3056 info.level = nil | |
| 3057 local button = AcquireButton(self, level) | |
| 3058 if not next(info) then | |
| 3059 info.disabled = true | |
| 3060 end | |
| 3061 button.disabled = info.isTitle or info.notClickable or info.disabled or (self.combat and info.secure) | |
| 3062 button.isTitle = info.isTitle | |
| 3063 button.notClickable = info.notClickable | |
| 3064 if button.isTitle then | |
| 3065 button.text:SetFontObject(GameFontNormalSmall) | |
| 3066 elseif button.notClickable then | |
| 3067 button.text:SetFontObject(GameFontHighlightSmall) | |
| 3068 elseif button.disabled then | |
| 3069 button.text:SetFontObject(GameFontDisableSmall) | |
| 3070 else | |
| 3071 button.text:SetFontObject(GameFontHighlightSmall) | |
| 3072 end | |
| 3073 if info.disabled then | |
| 3074 button.arrow:SetDesaturated(true) | |
| 3075 button.check:SetDesaturated(true) | |
| 3076 else | |
| 3077 button.arrow:SetDesaturated(false) | |
| 3078 button.check:SetDesaturated(false) | |
| 3079 end | |
| 3080 if info.textR and info.textG and info.textB then | |
| 3081 button.textR = info.textR | |
| 3082 button.textG = info.textG | |
| 3083 button.textB = info.textB | |
| 3084 button.text:SetTextColor(button.textR, button.textG, button.textB) | |
| 3085 else | |
| 3086 button.text:SetTextColor(button.text:GetFontObject():GetTextColor()) | |
| 3087 end | |
| 3088 button.notCheckable = info.notCheckable | |
| 3089 button.text:SetPoint("LEFT", button, "LEFT", button.notCheckable and 0 or 24, 0) | |
| 3090 button.checked = not info.notCheckable and info.checked | |
| 3091 button.mouseoverUnderline = info.mouseoverUnderline | |
| 3092 button.isRadio = not info.notCheckable and info.isRadio | |
| 3093 if info.isRadio then | |
| 3094 button.check:Show() | |
| 3095 button.check:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton") | |
| 3096 if button.checked then | |
| 3097 button.check:SetTexCoord(0.25, 0.5, 0, 1) | |
| 3098 button.check:SetVertexColor(1, 1, 1, 1) | |
| 3099 else | |
| 3100 button.check:SetTexCoord(0, 0.25, 0, 1) | |
| 3101 button.check:SetVertexColor(1, 1, 1, 0.5) | |
| 3102 end | |
| 3103 button.radioHighlight:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton") | |
| 3104 button.check:SetWidth(16) | |
| 3105 button.check:SetHeight(16) | |
| 3106 elseif info.icon then | |
| 3107 button.check:Show() | |
| 3108 button.check:SetTexture(info.icon) | |
| 3109 if info.iconWidth and info.iconHeight then | |
| 3110 button.check:SetWidth(info.iconWidth) | |
| 3111 button.check:SetHeight(info.iconHeight) | |
| 3112 else | |
| 3113 button.check:SetWidth(16) | |
| 3114 button.check:SetHeight(16) | |
| 3115 end | |
| 3116 if info.iconCoordLeft and info.iconCoordRight and info.iconCoordTop and info.iconCoordBottom then | |
| 3117 button.check:SetTexCoord(info.iconCoordLeft, info.iconCoordRight, info.iconCoordTop, info.iconCoordBottom) | |
| 3118 elseif info.icon:find("^Interface\\Icons\\") then | |
| 3119 button.check:SetTexCoord(0.05, 0.95, 0.05, 0.95) | |
| 3120 else | |
| 3121 button.check:SetTexCoord(0, 1, 0, 1) | |
| 3122 end | |
| 3123 button.check:SetVertexColor(1, 1, 1, 1) | |
| 3124 else | |
| 3125 if button.checked then | |
| 3126 if info.checkIcon then | |
| 3127 button.check:SetWidth(16) | |
| 3128 button.check:SetHeight(16) | |
| 3129 button.check:SetTexture(info.checkIcon) | |
| 3130 if info.checkIcon:find("^Interface\\Icons\\") then | |
| 3131 button.check:SetTexCoord(0.05, 0.95, 0.05, 0.95) | |
| 3132 else | |
| 3133 button.check:SetTexCoord(0, 1, 0, 1) | |
| 3134 end | |
| 3135 else | |
| 3136 button.check:SetWidth(24) | |
| 3137 button.check:SetHeight(24) | |
| 3138 button.check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") | |
| 3139 button.check:SetTexCoord(0, 1, 0, 1) | |
| 3140 end | |
| 3141 button.check:SetVertexColor(1, 1, 1, 1) | |
| 3142 else | |
| 3143 button.check:SetVertexColor(1, 1, 1, 0) | |
| 3144 end | |
| 3145 end | |
| 3146 if not button.disabled then | |
| 3147 button.func = info.func | |
| 3148 button.secure = info.secure | |
| 3149 end | |
| 3150 button.hasColorSwatch = info.hasColorSwatch | |
| 3151 if button.hasColorSwatch then | |
| 3152 button.colorSwatch:Show() | |
| 3153 button.colorSwatch.texture:Show() | |
| 3154 button.r = info.r or 1 | |
| 3155 button.g = info.g or 1 | |
| 3156 button.b = info.b or 1 | |
| 3157 button.colorSwatch.texture:SetVertexColor(button.r, button.g, button.b) | |
| 3158 button.checked = false | |
| 3159 button.func = nil | |
| 3160 button.colorFunc = info.colorFunc | |
| 3161 local i = 1 | |
| 3162 while true do | |
| 3163 local k = "colorArg" .. i | |
| 3164 local x = info[k] | |
| 3165 if x == nil then | |
| 3166 break | |
| 3167 end | |
| 3168 button[k] = x | |
| 3169 i = i + 1 | |
| 3170 end | |
| 3171 button.hasOpacity = info.hasOpacity | |
| 3172 button.opacity = info.opacity or 1 | |
| 3173 else | |
| 3174 button.colorSwatch:Hide() | |
| 3175 button.colorSwatch.texture:Hide() | |
| 3176 end | |
| 3177 button.hasArrow = not button.hasColorSwatch and (info.value or info.hasSlider or info.hasEditBox) and info.hasArrow | |
| 3178 if button.hasArrow then | |
| 3179 button.arrow:SetAlpha(1) | |
| 3180 if info.hasSlider then | |
| 3181 button.hasSlider = true | |
| 3182 button.sliderMin = info.sliderMin or 0 | |
| 3183 button.sliderMax = info.sliderMax or 1 | |
| 3184 button.sliderStep = info.sliderStep or 0 | |
| 3185 button.sliderBigStep = info.sliderBigStep or button.sliderStep | |
| 3186 if button.sliderBigStep < button.sliderStep then | |
| 3187 button.sliderBigStep = button.sliderStep | |
| 3188 end | |
| 3189 button.sliderIsPercent = info.sliderIsPercent and true or false | |
| 3190 button.sliderMinText = info.sliderMinText or button.sliderIsPercent and string.format("%.0f%%", button.sliderMin * 100) or button.sliderMin | |
| 3191 button.sliderMaxText = info.sliderMaxText or button.sliderIsPercent and string.format("%.0f%%", button.sliderMax * 100) or button.sliderMax | |
| 3192 button.sliderFunc = info.sliderFunc | |
| 3193 button.sliderValue = info.sliderValue | |
| 3194 button.fromAceOptions = info.fromAceOptions | |
| 3195 local i = 1 | |
| 3196 while true do | |
| 3197 local k = "sliderArg" .. i | |
| 3198 local x = info[k] | |
| 3199 if x == nil then | |
| 3200 break | |
| 3201 end | |
| 3202 button[k] = x | |
| 3203 i = i + 1 | |
| 3204 end | |
| 3205 elseif info.hasEditBox then | |
| 3206 button.hasEditBox = true | |
| 3207 button.editBoxText = info.editBoxText or "" | |
| 3208 button.editBoxFunc = info.editBoxFunc | |
| 3209 local i = 1 | |
| 3210 while true do | |
| 3211 local k = "editBoxArg" .. i | |
| 3212 local x = info[k] | |
| 3213 if x == nil then | |
| 3214 break | |
| 3215 end | |
| 3216 button[k] = x | |
| 3217 i = i + 1 | |
| 3218 end | |
| 3219 button.editBoxChangeFunc = info.editBoxChangeFunc | |
| 3220 local i = 1 | |
| 3221 while true do | |
| 3222 local k = "editBoxChangeArg" .. i | |
| 3223 local x = info[k] | |
| 3224 if x == nil then | |
| 3225 break | |
| 3226 end | |
| 3227 button[k] = x | |
| 3228 i = i + 1 | |
| 3229 end | |
| 3230 button.editBoxValidateFunc = info.editBoxValidateFunc | |
| 3231 local i = 1 | |
| 3232 while true do | |
| 3233 local k = "editBoxValidateArg" .. i | |
| 3234 local x = info[k] | |
| 3235 if x == nil then | |
| 3236 break | |
| 3237 end | |
| 3238 button[k] = x | |
| 3239 i = i + 1 | |
| 3240 end | |
| 3241 button.editBoxIsKeybinding = info.editBoxIsKeybinding | |
| 3242 button.editBoxKeybindingOnly = info.editBoxKeybindingOnly | |
| 3243 button.editBoxKeybindingExcept = info.editBoxKeybindingExcept | |
| 3244 else | |
| 3245 button.value = info.value | |
| 3246 local l = levels[level+1] | |
| 3247 if l and info.value == l.value then | |
| 3248 -- button.arrow:SetWidth(24) | |
| 3249 -- button.arrow:SetHeight(24) | |
| 3250 button.selected = true | |
| 3251 button.highlight:Show() | |
| 3252 end | |
| 3253 end | |
| 3254 else | |
| 3255 button.arrow:SetAlpha(0) | |
| 3256 end | |
| 3257 local i = 1 | |
| 3258 while true do | |
| 3259 local k = "arg" .. i | |
| 3260 local x = info[k] | |
| 3261 if x == nil then | |
| 3262 break | |
| 3263 end | |
| 3264 button[k] = x | |
| 3265 i = i + 1 | |
| 3266 end | |
| 3267 button.closeWhenClicked = info.closeWhenClicked | |
| 3268 button.textHeight = info.textHeight or UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT or 10 | |
| 3269 local font,_ = button.text:GetFont() | |
| 3270 button.text:SetFont(STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF", button.textHeight) | |
| 3271 button:SetHeight(button.textHeight + 6) | |
| 3272 button.text:SetPoint("RIGHT", button.arrow, (button.hasColorSwatch or button.hasArrow) and "LEFT" or "RIGHT") | |
| 3273 button.text:SetJustifyH(info.justifyH or "LEFT") | |
| 3274 button.text:SetText(info.text) | |
| 3275 button.tooltipTitle = info.tooltipTitle | |
| 3276 button.tooltipText = info.tooltipText | |
| 3277 button.tooltipFunc = info.tooltipFunc | |
| 3278 local i = 1 | |
| 3279 while true do | |
| 3280 local k = "tooltipArg" .. i | |
| 3281 local x = info[k] | |
| 3282 if x == nil then | |
| 3283 break | |
| 3284 end | |
| 3285 button[k] = x | |
| 3286 i = i + 1 | |
| 3287 end | |
| 3288 if not button.tooltipTitle and not button.tooltipText and not button.tooltipFunc and not info.isTitle then | |
| 3289 button.tooltipTitle = info.text | |
| 3290 end | |
| 3291 if type(button.func) == "string" then | |
| 3292 if type(button.arg1) ~= "table" then | |
| 3293 self:error("Cannot call method %q on a non-table", button.func) | |
| 3294 end | |
| 3295 if type(button.arg1[button.func]) ~= "function" then | |
| 3296 self:error("Method %q nonexistant.", button.func) | |
| 3297 end | |
| 3298 end | |
| 3299 end | |
| 3300 | |
| 3301 function Dewdrop:InjectAceOptionsTable(handler, options) | |
| 3302 self:argCheck(handler, 2, "table") | |
| 3303 self:argCheck(options, 3, "table") | |
| 3304 if tostring(options.type):lower() ~= "group" then | |
| 3305 self:error('Cannot inject into options table argument #3 if its type is not "group"') | |
| 3306 end | |
| 3307 if options.handler ~= nil and options.handler ~= handler then | |
| 3308 self:error("Cannot inject into options table argument #3 if it has a different handler than argument #2") | |
| 3309 end | |
| 3310 options.handler = handler | |
| 3311 local class = handler.class | |
| 3312 if not AceLibrary:HasInstance("AceOO-2.0") or not class then | |
| 3313 if Rock then | |
| 3314 -- possible Rock object | |
| 3315 for mixin in Rock:IterateObjectMixins(handler) do | |
| 3316 if type(mixin.GetAceOptionsDataTable) == "function" then | |
| 3317 local t = mixin:GetAceOptionsDataTable(handler) | |
| 3318 for k,v in pairs(t) do | |
| 3319 if type(options.args) ~= "table" then | |
| 3320 options.args = {} | |
| 3321 end | |
| 3322 if options.args[k] == nil then | |
| 3323 options.args[k] = v | |
| 3324 end | |
| 3325 end | |
| 3326 end | |
| 3327 end | |
| 3328 end | |
| 3329 else | |
| 3330 -- Ace2 object | |
| 3331 while class and class ~= AceLibrary("AceOO-2.0").Class do | |
| 3332 if type(class.GetAceOptionsDataTable) == "function" then | |
| 3333 local t = class:GetAceOptionsDataTable(handler) | |
| 3334 for k,v in pairs(t) do | |
| 3335 if type(options.args) ~= "table" then | |
| 3336 options.args = {} | |
| 3337 end | |
| 3338 if options.args[k] == nil then | |
| 3339 options.args[k] = v | |
| 3340 end | |
| 3341 end | |
| 3342 end | |
| 3343 local mixins = class.mixins | |
| 3344 if mixins then | |
| 3345 for mixin in pairs(mixins) do | |
| 3346 if type(mixin.GetAceOptionsDataTable) == "function" then | |
| 3347 local t = mixin:GetAceOptionsDataTable(handler) | |
| 3348 for k,v in pairs(t) do | |
| 3349 if type(options.args) ~= "table" then | |
| 3350 options.args = {} | |
| 3351 end | |
| 3352 if options.args[k] == nil then | |
| 3353 options.args[k] = v | |
| 3354 end | |
| 3355 end | |
| 3356 end | |
| 3357 end | |
| 3358 end | |
| 3359 class = class.super | |
| 3360 end | |
| 3361 end | |
| 3362 return options | |
| 3363 end | |
| 3364 | |
| 3365 function Dewdrop:OnTooltipHide() | |
| 3366 if lastSetFont then | |
| 3367 if lastSetFont == normalFont then | |
| 3368 lastSetFont = nil | |
| 3369 return | |
| 3370 end | |
| 3371 fillRegionTmp(GameTooltip:GetRegions()) | |
| 3372 for i,v in ipairs(regionTmp) do | |
| 3373 if v.GetFont then | |
| 3374 local font,size,outline = v:GetFont() | |
| 3375 if font == lastSetFont then | |
| 3376 v:SetFont(normalFont, size, outline) | |
| 3377 end | |
| 3378 end | |
| 3379 regionTmp[i] = nil | |
| 3380 end | |
| 3381 lastSetFont = nil | |
| 3382 end | |
| 3383 end | |
| 3384 | |
| 3385 local function activate(self, oldLib, oldDeactivate) | |
| 3386 Dewdrop = self | |
| 3387 if oldLib and oldLib.registry then | |
| 3388 self.registry = oldLib.registry | |
| 3389 self.onceRegistered = oldLib.onceRegistered | |
| 3390 else | |
| 3391 self.registry = {} | |
| 3392 self.onceRegistered = {} | |
| 3393 | |
| 3394 local WorldFrame_OnMouseDown = WorldFrame:GetScript("OnMouseDown") | |
| 3395 local WorldFrame_OnMouseUp = WorldFrame:GetScript("OnMouseUp") | |
| 3396 local oldX, oldY, clickTime | |
| 3397 WorldFrame:SetScript("OnMouseDown", function(this, ...) | |
| 3398 oldX,oldY = GetCursorPosition() | |
| 3399 clickTime = GetTime() | |
| 3400 if WorldFrame_OnMouseDown then | |
| 3401 WorldFrame_OnMouseDown(this, ...) | |
| 3402 end | |
| 3403 end) | |
| 3404 | |
| 3405 WorldFrame:SetScript("OnMouseUp", function(this, ...) | |
| 3406 local x,y = GetCursorPosition() | |
| 3407 if not oldX or not oldY or not x or not y or not clickTime then | |
| 3408 self:Close() | |
| 3409 if WorldFrame_OnMouseUp then | |
| 3410 WorldFrame_OnMouseUp(this, ...) | |
| 3411 end | |
| 3412 return | |
| 3413 end | |
| 3414 local d = math.abs(x - oldX) + math.abs(y - oldY) | |
| 3415 if d <= 5 and GetTime() - clickTime < 0.5 then | |
| 3416 self:Close() | |
| 3417 end | |
| 3418 if WorldFrame_OnMouseUp then | |
| 3419 WorldFrame_OnMouseUp(this, ...) | |
| 3420 end | |
| 3421 end) | |
| 3422 | |
| 3423 hooksecurefunc(DropDownList1, "Show", function() | |
| 3424 if levels[1] and levels[1]:IsVisible() then | |
| 3425 self:Close() | |
| 3426 end | |
| 3427 end) | |
| 3428 | |
| 3429 hooksecurefunc("HideDropDownMenu", function() | |
| 3430 if levels[1] and levels[1]:IsVisible() then | |
| 3431 self:Close() | |
| 3432 end | |
| 3433 end) | |
| 3434 | |
| 3435 hooksecurefunc("CloseDropDownMenus", function() | |
| 3436 if levels[1] and levels[1]:IsVisible() then | |
| 3437 local stack = debugstack() | |
| 3438 if not stack:find("`TargetFrame_OnHide'") then | |
| 3439 self:Close() | |
| 3440 end | |
| 3441 end | |
| 3442 end) | |
| 3443 end | |
| 3444 self.frame = oldLib and oldLib.frame or CreateFrame("Frame") | |
| 3445 self.frame:UnregisterAllEvents() | |
| 3446 self.frame:RegisterEvent("PLAYER_REGEN_ENABLED") | |
| 3447 self.frame:RegisterEvent("PLAYER_REGEN_DISABLED") | |
| 3448 self.frame:Hide() | |
| 3449 self.frame:SetScript("OnEvent", function(this, event) | |
| 3450 this:Show() | |
| 3451 if event=="PLAYER_REGEN_ENABLED" then -- track combat state for secure frame operations | |
| 3452 self.combat = false | |
| 3453 elseif event=="PLAYER_REGEN_DISABLED" then | |
| 3454 self.combat = true | |
| 3455 end | |
| 3456 end) | |
| 3457 self.frame:SetScript("OnUpdate", function(this) | |
| 3458 this:Hide() | |
| 3459 self:Refresh(1) | |
| 3460 end) | |
| 3461 self.hookedTooltip = true | |
| 3462 if not oldLib or not oldLib.hookedTooltip then | |
| 3463 local OnTooltipHide = GameTooltip:GetScript("OnHide") | |
| 3464 GameTooltip:SetScript("OnHide", function(this, ...) | |
| 3465 if OnTooltipHide then | |
| 3466 OnTooltipHide(this, ...) | |
| 3467 end | |
| 3468 if type(self.OnTooltipHide) == "function" then | |
| 3469 self:OnTooltipHide() | |
| 3470 end | |
| 3471 end) | |
| 3472 end | |
| 3473 levels = {} | |
| 3474 buttons = {} | |
| 3475 | |
| 3476 if oldDeactivate then | |
| 3477 oldDeactivate(oldLib) | |
| 3478 end | |
| 3479 end | |
| 3480 | |
| 3481 local function external(lib, major, instance) | |
| 3482 if major == "SharedMedia-1.0" then | |
| 3483 SharedMedia = instance | |
| 3484 end | |
| 3485 end | |
| 3486 | |
| 3487 AceLibrary:Register(Dewdrop, MAJOR_VERSION, MINOR_VERSION, activate, nil, external) |
