Guest User

Untitled

a guest
Nov 22nd, 2022
520
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 51.72 KB | None | 0 0
  1. local AngryNotes = LibStub("AceAddon-3.0"):NewAddon("AngryNotes", "AceConsole-3.0", "AceEvent-3.0")
  2. local AceGUI = LibStub("AceGUI-3.0")
  3. local lwin = LibStub("LibWindow-1.1")
  4. local LSM = LibStub("LibSharedMedia-3.0")
  5.  
  6. BINDING_HEADER_AngryNotes = "Angry Notes"
  7. BINDING_NAME_AngryNotes_WINDOW = "Toggle Window"
  8. BINDING_NAME_AngryNotes_LOCK = "Toggle Lock"
  9. BINDING_NAME_AngryNotes_DISPLAY = "Toggle Display"
  10. BINDING_NAME_AngryNotes_OUTPUT = "Output Note to Chat"
  11.  
  12. local AngryNotes_Version = 'v0.4.1'
  13. local AngryNotes_Timestamp = '20201025015549'
  14.  
  15. local currentGroup = nil
  16.  
  17. -- Pages Saved Variable Format
  18. -- AngryNotes_Pages = {
  19. -- [Id] = { Id = "1231", Name = "Name", Contents = "...", CategoryId = 123 },
  20. -- ...
  21. -- }
  22. -- AngryNotes_Categories = {
  23. -- [Id] = { Id = "1231", Name = "Name", CategoryId = 123 },
  24. -- ...
  25. -- }
  26.  
  27. -----------------------
  28. -- Utility Functions --
  29. -----------------------
  30.  
  31. local function selectedLastValue(input)
  32. local a = select(-1, strsplit("", input or ""))
  33. return tonumber(a)
  34. end
  35.  
  36. local function tReverse(tbl)
  37. for i=1, math.floor(#tbl / 2) do
  38. tbl[i], tbl[#tbl - i + 1] = tbl[#tbl - i + 1], tbl[i]
  39. end
  40. end
  41.  
  42. local _player_realm = nil
  43. local function EnsureUnitFullName(unit)
  44. if not _player_realm then _player_realm = select(2, UnitFullName('player')) end
  45. if unit and not unit:find('-') then
  46. unit = unit..'-'.._player_realm
  47. end
  48. return unit
  49. end
  50.  
  51. local function EnsureUnitShortName(unit)
  52. if not _player_realm then _player_realm = select(2, UnitFullName('player')) end
  53. local name, realm = strsplit("-", unit, 2)
  54. if not realm or realm == _player_realm then
  55. return name
  56. else
  57. return unit
  58. end
  59. end
  60.  
  61. local function PlayerFullName()
  62. if not _player_realm then _player_realm = select(2, UnitFullName('player')) end
  63. return UnitName('player')..'-'.._player_realm
  64. end
  65.  
  66. local function RGBToHex(r, g, b, a)
  67. r = math.ceil(255 * r)
  68. g = math.ceil(255 * g)
  69. b = math.ceil(255 * b)
  70. if a == nil then
  71. return string.format("%02x%02x%02x", r, g, b)
  72. else
  73. a = math.ceil(255 * a)
  74. return string.format("%02x%02x%02x%02x", r, g, b, a)
  75. end
  76. end
  77.  
  78. local function HexToRGB(hex)
  79. if string.len(hex) == 8 then
  80. return tonumber("0x"..hex:sub(1,2)) / 255, tonumber("0x"..hex:sub(3,4)) / 255, tonumber("0x"..hex:sub(5,6)) / 255, tonumber("0x"..hex:sub(7,8)) / 255
  81. else
  82. return tonumber("0x"..hex:sub(1,2)) / 255, tonumber("0x"..hex:sub(3,4)) / 255, tonumber("0x"..hex:sub(5,6)) / 255
  83. end
  84. end
  85.  
  86. -------------------------
  87. -- Addon Communication --
  88. -------------------------
  89.  
  90. function AngryNotes:GetCurrentGroup()
  91. local player = PlayerFullName()
  92. if (IsInRaid() or IsInGroup()) then
  93. for i = 1, GetNumGroupMembers() do
  94. local name, _, subgroup = GetRaidRosterInfo(i)
  95. if EnsureUnitFullName(name) == player then
  96. return subgroup
  97. end
  98. end
  99. end
  100. return nil
  101. end
  102.  
  103. --------------------------
  104. -- Editing Pages Window --
  105. --------------------------
  106.  
  107. function AngryNotes_ToggleWindow()
  108. if not AngryNotes.window then AngryNotes:CreateWindow() end
  109. if AngryNotes.window:IsShown() then
  110. AngryNotes.window:Hide()
  111. else
  112. AngryNotes.window:Show()
  113. end
  114. end
  115.  
  116. function AngryNotes_ToggleLock()
  117. AngryNotes:ToggleLock()
  118. end
  119.  
  120. local function AngryNotes_AddPage(widget, event, value)
  121. local popup_name = "AngryNotes_AddPage"
  122. if StaticPopupDialogs[popup_name] == nil then
  123. StaticPopupDialogs[popup_name] = {
  124. button1 = OKAY,
  125. button2 = CANCEL,
  126. OnAccept = function(self)
  127. local text = self.editBox:GetText()
  128. if text ~= "" then AngryNotes:CreatePage(text) end
  129. end,
  130. EditBoxOnEnterPressed = function(self)
  131. local text = self:GetParent().editBox:GetText()
  132. if text ~= "" then AngryNotes:CreatePage(text) end
  133. self:GetParent():Hide()
  134. end,
  135. text = "New page name:",
  136. hasEditBox = true,
  137. whileDead = true,
  138. EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
  139. hideOnEscape = true,
  140. preferredIndex = 3
  141. }
  142. end
  143. StaticPopup_Show(popup_name)
  144. end
  145.  
  146. local function AngryNotes_RenamePage(pageId)
  147. local page = AngryNotes:Get(pageId)
  148. if not page then return end
  149.  
  150. local popup_name = "AngryNotes_RenamePage_"..page.Id
  151. if StaticPopupDialogs[popup_name] == nil then
  152. StaticPopupDialogs[popup_name] = {
  153. button1 = OKAY,
  154. button2 = CANCEL,
  155. OnAccept = function(self)
  156. local text = self.editBox:GetText()
  157. AngryNotes:RenamePage(page.Id, text)
  158. end,
  159. EditBoxOnEnterPressed = function(self)
  160. local text = self:GetParent().editBox:GetText()
  161. AngryNotes:RenamePage(page.Id, text)
  162. self:GetParent():Hide()
  163. end,
  164. OnShow = function(self)
  165. self.editBox:SetText(page.Name)
  166. end,
  167. whileDead = true,
  168. hasEditBox = true,
  169. EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
  170. hideOnEscape = true,
  171. preferredIndex = 3
  172. }
  173. end
  174. StaticPopupDialogs[popup_name].text = 'Rename page "'.. page.Name ..'" to:'
  175.  
  176. StaticPopup_Show(popup_name)
  177. end
  178.  
  179. local function AngryNotes_DeletePage(pageId)
  180. local page = AngryNotes:Get(pageId)
  181. if not page then return end
  182.  
  183. local popup_name = "AngryNotes_DeletePage_"..page.Id
  184. if StaticPopupDialogs[popup_name] == nil then
  185. StaticPopupDialogs[popup_name] = {
  186. button1 = OKAY,
  187. button2 = CANCEL,
  188. OnAccept = function(self)
  189. AngryNotes:DeletePage(page.Id)
  190. end,
  191. whileDead = true,
  192. hideOnEscape = true,
  193. preferredIndex = 3
  194. }
  195. end
  196. StaticPopupDialogs[popup_name].text = 'Are you sure you want to delete page "'.. page.Name ..'"?'
  197.  
  198. StaticPopup_Show(popup_name)
  199. end
  200.  
  201. local function AngryNotes_AddCategory(widget, event, value)
  202. local popup_name = "AngryNotes_AddCategory"
  203. if StaticPopupDialogs[popup_name] == nil then
  204. StaticPopupDialogs[popup_name] = {
  205. button1 = OKAY,
  206. button2 = CANCEL,
  207. OnAccept = function(self)
  208. local text = self.editBox:GetText()
  209. if text ~= "" then AngryNotes:CreateCategory(text) end
  210. end,
  211. EditBoxOnEnterPressed = function(self)
  212. local text = self:GetParent().editBox:GetText()
  213. if text ~= "" then AngryNotes:CreateCategory(text) end
  214. self:GetParent():Hide()
  215. end,
  216. text = "New category name:",
  217. hasEditBox = true,
  218. whileDead = true,
  219. EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
  220. hideOnEscape = true,
  221. preferredIndex = 3
  222. }
  223. end
  224. StaticPopup_Show(popup_name)
  225. end
  226.  
  227. local function AngryNotes_RenameCategory(catId)
  228. local cat = AngryNotes:GetCat(catId)
  229. if not cat then return end
  230.  
  231. local popup_name = "AngryNotes_RenameCategory_"..cat.Id
  232. if StaticPopupDialogs[popup_name] == nil then
  233. StaticPopupDialogs[popup_name] = {
  234. button1 = OKAY,
  235. button2 = CANCEL,
  236. OnAccept = function(self)
  237. local text = self.editBox:GetText()
  238. AngryNotes:RenameCategory(cat.Id, text)
  239. end,
  240. EditBoxOnEnterPressed = function(self)
  241. local text = self:GetParent().editBox:GetText()
  242. AngryNotes:RenameCategory(cat.Id, text)
  243. self:GetParent():Hide()
  244. end,
  245. OnShow = function(self)
  246. self.editBox:SetText(cat.Name)
  247. end,
  248. whileDead = true,
  249. hasEditBox = true,
  250. EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
  251. hideOnEscape = true,
  252. preferredIndex = 3
  253. }
  254. end
  255. StaticPopupDialogs[popup_name].text = 'Rename category "'.. cat.Name ..'" to:'
  256.  
  257. StaticPopup_Show(popup_name)
  258. end
  259.  
  260. local function AngryNotes_DeleteCategory(catId)
  261. local cat = AngryNotes:GetCat(catId)
  262. if not cat then return end
  263.  
  264. local popup_name = "AngryNotes_DeleteCategory_"..cat.Id
  265. if StaticPopupDialogs[popup_name] == nil then
  266. StaticPopupDialogs[popup_name] = {
  267. button1 = OKAY,
  268. button2 = CANCEL,
  269. OnAccept = function(self)
  270. AngryNotes:DeleteCategory(cat.Id)
  271. end,
  272. whileDead = true,
  273. hideOnEscape = true,
  274. preferredIndex = 3
  275. }
  276. end
  277. StaticPopupDialogs[popup_name].text = 'Are you sure you want to delete category "'.. cat.Name ..'"?'
  278.  
  279. StaticPopup_Show(popup_name)
  280. end
  281.  
  282. local function AngryNotes_AssignCategory(frame, entryId, catId)
  283. HideDropDownMenu(1)
  284.  
  285. AngryNotes:AssignCategory(entryId, catId)
  286. end
  287.  
  288. local function AngryNotes_RevertPage(widget, event, value)
  289. if not AngryNotes.window then return end
  290. AngryNotes:UpdateSelected(true)
  291. end
  292.  
  293. function AngryNotes:DisplayPageByName( name )
  294. for id, page in pairs(AngryNotes_Pages) do
  295. if page.Name == name then
  296. return self:DisplayPage( id )
  297. end
  298. end
  299. return false
  300. end
  301.  
  302. function AngryNotes:DisplayPage( id )
  303.  
  304. if AngryNotes_State.displayed ~= id then
  305. AngryNotes_State.displayed = id
  306. AngryNotes:UpdateDisplayed()
  307. AngryNotes:ShowDisplay()
  308. AngryNotes:UpdateTree()
  309. end
  310.  
  311. return true
  312. end
  313.  
  314. local function AngryNotes_DisplayPage(widget, event, value)
  315. local id = AngryNotes:SelectedId()
  316. AngryNotes:DisplayPage( id )
  317. end
  318.  
  319. local function AngryNotes_ClearPage(widget, event, value)
  320. AngryNotes:ClearDisplayed()
  321. end
  322.  
  323. local function AngryNotes_TextChanged(widget, event, value)
  324. AngryNotes.window.button_revert:SetDisabled(false)
  325. AngryNotes.window.button_display:SetDisabled(true)
  326. AngryNotes.window.button_output:SetDisabled(true)
  327. end
  328.  
  329. local function AngryNotes_TextEntered(widget, event, value)
  330. AngryNotes:UpdateContents(AngryNotes:SelectedId(), value)
  331. end
  332.  
  333. local function AngryNotes_CategoryMenuList(entryId, parentId)
  334. local categories = {}
  335.  
  336. local checkedId
  337. if entryId > 0 then
  338. local page = AngryNotes_Pages[entryId]
  339. checkedId = page.CategoryId
  340. else
  341. local cat = AngryNotes_Categories[-entryId]
  342. checkedId = cat.CategoryId
  343. end
  344.  
  345. for _, cat in pairs(AngryNotes_Categories) do
  346. if cat.Id ~= -entryId and (parentId or not cat.CategoryId) and (not parentId or cat.CategoryId == parentId) then
  347. local subMenu = AngryNotes_CategoryMenuList(entryId, cat.Id)
  348. table.insert(categories, { text = cat.Name, value = cat.Id, menuList = subMenu, hasArrow = (subMenu ~= nil), checked = (checkedId == cat.Id), func = AngryNotes_AssignCategory, arg1 = entryId, arg2 = cat.Id })
  349. end
  350. end
  351.  
  352. table.sort(categories, function(a,b) return a.text < b.text end)
  353.  
  354. if #categories > 0 then
  355. return categories
  356. end
  357. end
  358.  
  359. local PagesDropDownList
  360. function AngryNotes_PageMenu(pageId)
  361. local page = AngryNotes_Pages[pageId]
  362. if not page then return end
  363.  
  364. if not PagesDropDownList then
  365. PagesDropDownList = {
  366. { notCheckable = true, isTitle = true },
  367. { text = "Rename", notCheckable = true, func = function(frame, pageId) AngryNotes_RenamePage(pageId) end },
  368. { text = "Delete", notCheckable = true, func = function(frame, pageId) AngryNotes_DeletePage(pageId) end },
  369. { text = "Category", notCheckable = true, hasArrow = true },
  370. }
  371. end
  372.  
  373. PagesDropDownList[1].text = page.Name
  374. PagesDropDownList[2].arg1 = pageId
  375. PagesDropDownList[3].arg1 = pageId
  376.  
  377. local categories = AngryNotes_CategoryMenuList(pageId)
  378. if categories ~= nil then
  379. PagesDropDownList[4].menuList = categories
  380. PagesDropDownList[4].disabled = false
  381. else
  382. PagesDropDownList[4].menuList = {}
  383. PagesDropDownList[4].disabled = true
  384. end
  385. return PagesDropDownList
  386. end
  387.  
  388. local CategoriesDropDownList
  389. local function AngryNotes_CategoryMenu(catId)
  390. local cat = AngryNotes_Categories[catId]
  391. if not cat then return end
  392.  
  393. if not CategoriesDropDownList then
  394. CategoriesDropDownList = {
  395. { notCheckable = true, isTitle = true },
  396. { text = "Rename", notCheckable = true, func = function(frame, pageId) AngryNotes_RenameCategory(pageId) end },
  397. { text = "Delete", notCheckable = true, func = function(frame, pageId) AngryNotes_DeleteCategory(pageId) end },
  398. { text = "Category", notCheckable = true, hasArrow = true },
  399. }
  400. end
  401. CategoriesDropDownList[1].text = cat.Name
  402. CategoriesDropDownList[2].arg1 = catId
  403. CategoriesDropDownList[3].arg1 = catId
  404.  
  405. local categories = AngryNotes_CategoryMenuList(-catId)
  406. if categories ~= nil then
  407. CategoriesDropDownList[4].menuList = categories
  408. CategoriesDropDownList[4].disabled = false
  409. else
  410. CategoriesDropDownList[4].menuList = {}
  411. CategoriesDropDownList[4].disabled = true
  412. end
  413.  
  414. return CategoriesDropDownList
  415. end
  416.  
  417. local AngryNotes_DropDown
  418. local function AngryNotes_TreeClick(widget, event, value, selected, button)
  419. HideDropDownMenu(1)
  420. local selectedId = selectedLastValue(value)
  421. if selectedId < 0 then
  422. if button == "RightButton" then
  423. if not AngryNotes_DropDown then
  424. AngryNotes_DropDown = CreateFrame("Frame", "AngryNotesMenuFrame", UIParent, "UIDropDownMenuTemplate")
  425. end
  426. EasyMenu(AngryNotes_CategoryMenu(-selectedId), AngryNotes_DropDown, "cursor", 0 , 0, "MENU")
  427.  
  428. else
  429. local status = (widget.status or widget.localstatus).groups
  430. status[value] = not status[value]
  431. widget:RefreshTree()
  432. end
  433. return false
  434. else
  435. if button == "RightButton" then
  436. if not AngryNotes_DropDown then
  437. AngryNotes_DropDown = CreateFrame("Frame", "AngryNotesMenuFrame", UIParent, "UIDropDownMenuTemplate")
  438. end
  439. EasyMenu(AngryNotes_PageMenu(selectedId), AngryNotes_DropDown, "cursor", 0 , 0, "MENU")
  440.  
  441. return false
  442. end
  443. end
  444. end
  445.  
  446. function AngryNotes:CreateWindow()
  447. local window = AceGUI:Create("Frame")
  448. window:SetTitle("Angry Notes")
  449. window:SetStatusText("")
  450. window:SetLayout("Flow")
  451. if AngryNotes:GetConfig('scale') then window.frame:SetScale( AngryNotes:GetConfig('scale') ) end
  452. window:SetStatusTable(AngryNotes_State.window)
  453. window:Hide()
  454. AngryNotes.window = window
  455.  
  456. AngryNotes_Window = window.frame
  457. window.frame:SetResizeBounds(700, 400)
  458. window.frame:SetFrameStrata("HIGH")
  459. window.frame:SetFrameLevel(1)
  460. tinsert(UISpecialFrames, "AngryNotes_Window")
  461.  
  462. local tree = AceGUI:Create("AngryTreeGroup")
  463. tree:SetTree( self:GetTree() )
  464. tree:SelectByValue(1)
  465. tree:SetStatusTable(AngryNotes_State.tree)
  466. tree:SetFullWidth(true)
  467. tree:SetFullHeight(true)
  468. tree:SetLayout("Flow")
  469. tree:SetCallback("OnGroupSelected", function(widget, event, value) AngryNotes:UpdateSelected(true) end)
  470. tree:SetCallback("OnClick", AngryNotes_TreeClick)
  471. window:AddChild(tree)
  472. window.tree = tree
  473.  
  474. local text = AceGUI:Create("MultiLineEditBox")
  475. text:SetLabel(nil)
  476. text:SetFullWidth(true)
  477. text:SetFullHeight(true)
  478. text:SetCallback("OnTextChanged", AngryNotes_TextChanged)
  479. text:SetCallback("OnEnterPressed", AngryNotes_TextEntered)
  480. tree:AddChild(text)
  481. window.text = text
  482. text.button:SetWidth(75)
  483. local buttontext = text.button:GetFontString()
  484. buttontext:ClearAllPoints()
  485. buttontext:SetPoint("TOPLEFT", text.button, "TOPLEFT", 15, -1)
  486. buttontext:SetPoint("BOTTOMRIGHT", text.button, "BOTTOMRIGHT", -15, 1)
  487.  
  488. tree:PauseLayout()
  489. local button_display = AceGUI:Create("Button")
  490. button_display:SetText("Display")
  491. button_display:SetWidth(100)
  492. button_display:SetHeight(22)
  493. button_display:ClearAllPoints()
  494. button_display:SetPoint("BOTTOMRIGHT", text.frame, "BOTTOMRIGHT", 0, 4)
  495. button_display:SetCallback("OnClick", AngryNotes_DisplayPage)
  496. tree:AddChild(button_display)
  497. window.button_display = button_display
  498.  
  499. local button_revert = AceGUI:Create("Button")
  500. button_revert:SetText("Revert")
  501. button_revert:SetWidth(80)
  502. button_revert:SetHeight(22)
  503. button_revert:ClearAllPoints()
  504. button_revert:SetDisabled(true)
  505. button_revert:SetPoint("BOTTOMLEFT", text.button, "BOTTOMRIGHT", 6, 0)
  506. button_revert:SetCallback("OnClick", AngryNotes_RevertPage)
  507. tree:AddChild(button_revert)
  508. window.button_revert = button_revert
  509.  
  510. local button_output = AceGUI:Create("Button")
  511. button_output:SetText("Output")
  512. button_output:SetWidth(80)
  513. button_output:SetHeight(22)
  514. button_output:ClearAllPoints()
  515. button_output:SetPoint("BOTTOMRIGHT", button_display.frame, "BOTTOMLEFT", -6, 0)
  516. button_output:SetCallback("OnClick", AngryNotes_OutputDisplayed)
  517. tree:AddChild(button_output)
  518. window.button_output = button_output
  519.  
  520. window:PauseLayout()
  521. local button_add = AceGUI:Create("Button")
  522. button_add:SetText("Add")
  523. button_add:SetWidth(80)
  524. button_add:SetHeight(19)
  525. button_add:ClearAllPoints()
  526. button_add:SetPoint("BOTTOMLEFT", window.frame, "BOTTOMLEFT", 17, 18)
  527. button_add:SetCallback("OnClick", AngryNotes_AddPage)
  528. window:AddChild(button_add)
  529. window.button_add = button_add
  530.  
  531. local button_rename = AceGUI:Create("Button")
  532. button_rename:SetText("Rename")
  533. button_rename:SetWidth(80)
  534. button_rename:SetHeight(19)
  535. button_rename:ClearAllPoints()
  536. button_rename:SetPoint("BOTTOMLEFT", button_add.frame, "BOTTOMRIGHT", 5, 0)
  537. button_rename:SetCallback("OnClick", function() AngryNotes_RenamePage() end)
  538. window:AddChild(button_rename)
  539. window.button_rename = button_rename
  540.  
  541. local button_delete = AceGUI:Create("Button")
  542. button_delete:SetText("Delete")
  543. button_delete:SetWidth(80)
  544. button_delete:SetHeight(19)
  545. button_delete:ClearAllPoints()
  546. button_delete:SetPoint("BOTTOMLEFT", button_rename.frame, "BOTTOMRIGHT", 5, 0)
  547. button_delete:SetCallback("OnClick", function() AngryNotes_DeletePage() end)
  548. window:AddChild(button_delete)
  549. window.button_delete = button_delete
  550.  
  551. local button_add_cat = AceGUI:Create("Button")
  552. button_add_cat:SetText("Add Category")
  553. button_add_cat:SetWidth(120)
  554. button_add_cat:SetHeight(19)
  555. button_add_cat:ClearAllPoints()
  556. button_add_cat:SetPoint("BOTTOMLEFT", button_delete.frame, "BOTTOMRIGHT", 5, 0)
  557. button_add_cat:SetCallback("OnClick", function() AngryNotes_AddCategory() end)
  558. window:AddChild(button_add_cat)
  559. window.button_add_cat = button_add_cat
  560.  
  561. local button_clear = AceGUI:Create("Button")
  562. button_clear:SetText("Clear")
  563. button_clear:SetWidth(80)
  564. button_clear:SetHeight(19)
  565. button_clear:ClearAllPoints()
  566. button_clear:SetPoint("BOTTOMRIGHT", window.frame, "BOTTOMRIGHT", -135, 18)
  567. button_clear:SetCallback("OnClick", AngryNotes_ClearPage)
  568. window:AddChild(button_clear)
  569. window.button_clear = button_clear
  570.  
  571. self:UpdateSelected(true)
  572. self:UpdateMedia()
  573.  
  574. --self:CreateIconPicker()
  575. end
  576.  
  577. local function GetTree_InsertPage(tree, page)
  578. if page.Id == AngryNotes_State.displayed then
  579. table.insert(tree, { value = page.Id, text = page.Name, icon = "Interface\\BUTTONS\\UI-GuildButton-MOTD-Up" })
  580. else
  581. table.insert(tree, { value = page.Id, text = page.Name })
  582. end
  583. end
  584.  
  585. local function GetTree_InsertChildren(categoryId, displayedPages)
  586. local tree = {}
  587. for _, cat in pairs(AngryNotes_Categories) do
  588. if cat.CategoryId == categoryId then
  589. table.insert(tree, { value = -cat.Id, text = cat.Name, children = GetTree_InsertChildren(cat.Id, displayedPages) })
  590. end
  591. end
  592.  
  593. for _, page in pairs(AngryNotes_Pages) do
  594. if page.CategoryId == categoryId then
  595. displayedPages[page.Id] = true
  596. GetTree_InsertPage(tree, page)
  597. end
  598. end
  599.  
  600. table.sort(tree, function(a,b) return a.text < b.text end)
  601. return tree
  602. end
  603.  
  604. function AngryNotes:GetTree()
  605. local tree = {}
  606. local displayedPages = {}
  607.  
  608. for _, cat in pairs(AngryNotes_Categories) do
  609. if not cat.CategoryId then
  610. table.insert(tree, { value = -cat.Id, text = cat.Name, children = GetTree_InsertChildren(cat.Id, displayedPages) })
  611. end
  612. end
  613.  
  614. for _, page in pairs(AngryNotes_Pages) do
  615. if not page.CategoryId or not displayedPages[page.Id] then
  616. GetTree_InsertPage(tree, page)
  617. end
  618. end
  619.  
  620. table.sort(tree, function(a,b) return a.text < b.text end)
  621.  
  622. return tree
  623. end
  624.  
  625. function AngryNotes:UpdateTree(id)
  626. if not self.window then return end
  627. self.window.tree:SetTree( self:GetTree() )
  628. if id then
  629. self:SetSelectedId( id )
  630. end
  631. end
  632.  
  633. function AngryNotes:UpdateSelected(destructive)
  634. if not self.window then return end
  635. local page = AngryNotes_Pages[ self:SelectedId() ]
  636. if destructive or not self.window.text.button:IsEnabled() then
  637. if page then
  638. self.window.text:SetText( page.Contents )
  639. else
  640. self.window.text:SetText("")
  641. end
  642. self.window.text.button:Disable()
  643. end
  644. if page then
  645. self.window.button_rename:SetDisabled(false)
  646. self.window.button_revert:SetDisabled(not self.window.text.button:IsEnabled())
  647. self.window.button_display:SetDisabled(false)
  648. self.window.button_output:SetDisabled(false)
  649. self.window.text:SetDisabled(false)
  650. else
  651. self.window.button_rename:SetDisabled(true)
  652. self.window.button_revert:SetDisabled(true)
  653. self.window.button_display:SetDisabled(true)
  654. self.window.button_output:SetDisabled(true)
  655. self.window.text:SetDisabled(true)
  656. end
  657. if page then
  658. self.window.button_delete:SetDisabled(false)
  659. else
  660. self.window.button_delete:SetDisabled(true)
  661. end
  662. self.window.button_add:SetDisabled(false)
  663. self.window.button_clear:SetDisabled(false)
  664. end
  665.  
  666. ----------------------------------
  667. -- Performing changes functions --
  668. ----------------------------------
  669.  
  670. function AngryNotes:SelectedId()
  671. return selectedLastValue( AngryNotes_State.tree.selected )
  672. end
  673.  
  674. function AngryNotes:SetSelectedId(selectedId)
  675. local page = AngryNotes_Pages[selectedId]
  676. if page then
  677. if page.CategoryId then
  678. local cat = AngryNotes_Categories[page.CategoryId]
  679. local path = { }
  680. while cat do
  681. table.insert(path, -cat.Id)
  682. if cat.CategoryId then
  683. cat = AngryNotes_Categories[cat.CategoryId]
  684. else
  685. cat = nil
  686. end
  687. end
  688. tReverse(path)
  689. table.insert(path, page.Id)
  690. self.window.tree:SelectByPath(unpack(path))
  691. else
  692. self.window.tree:SelectByValue(page.Id)
  693. end
  694. else
  695. self.window.tree:SetSelected()
  696. end
  697. end
  698.  
  699. function AngryNotes:Get(id)
  700. if id == nil then id = self:SelectedId() end
  701. return AngryNotes_Pages[id]
  702. end
  703.  
  704. function AngryNotes:GetCat(id)
  705. return AngryNotes_Categories[id]
  706. end
  707.  
  708. function AngryNotes:CreatePage(name)
  709. local id = math.random(2000000000)
  710.  
  711. AngryNotes_Pages[id] = { Id = id, Name = name, Contents = "" }
  712. self:UpdateTree(id)
  713. end
  714.  
  715. function AngryNotes:RenamePage(id, name)
  716. local page = self:Get(id)
  717.  
  718. page.Name = name
  719.  
  720. if AngryNotes_State.displayed == id then
  721. self:UpdateDisplayed()
  722. self:ShowDisplay()
  723. end
  724. end
  725.  
  726. function AngryNotes:DeletePage(id)
  727. AngryNotes_Pages[id] = nil
  728. if self.window and self:SelectedId() == id then
  729. self:SetSelectedId(nil)
  730. self:UpdateSelected(true)
  731. end
  732. if AngryNotes_State.displayed == id then
  733. self:ClearDisplayed()
  734. end
  735. self:UpdateTree()
  736. end
  737.  
  738. function AngryNotes:CreateCategory(name)
  739. local id = math.random(2000000000)
  740.  
  741. AngryNotes_Categories[id] = { Id = id, Name = name }
  742.  
  743. if AngryNotes_State.tree.groups then
  744. AngryNotes_State.tree.groups[ -id ] = true
  745. end
  746. self:UpdateTree()
  747. end
  748.  
  749. function AngryNotes:RenameCategory(id, name)
  750. local cat = self:GetCat(id)
  751. if not cat then return end
  752.  
  753. cat.Name = name
  754.  
  755. self:UpdateTree()
  756. end
  757.  
  758. function AngryNotes:DeleteCategory(id)
  759. local cat = self:GetCat(id)
  760. if not cat then return end
  761.  
  762. local selectedId = self:SelectedId()
  763.  
  764. for _, c in pairs(AngryNotes_Categories) do
  765. if cat.Id == c.CategoryId then
  766. c.CategoryId = cat.CategoryId
  767. end
  768. end
  769.  
  770. for _, p in pairs(AngryNotes_Pages) do
  771. if cat.Id == p.CategoryId then
  772. p.CategoryId = cat.CategoryId
  773. end
  774. end
  775.  
  776. AngryNotes_Categories[id] = nil
  777.  
  778. self:UpdateTree()
  779. self:SetSelectedId(selectedId)
  780. end
  781.  
  782. function AngryNotes:AssignCategory(entryId, parentId)
  783. local page, cat
  784. if entryId > 0 then
  785. page = self:Get(entryId)
  786. else
  787. cat = self:GetCat(-entryId)
  788. end
  789. local parent = self:GetCat(parentId)
  790. if not (page or cat) or not parent then return end
  791.  
  792. if page then
  793. if page.CategoryId == parentId then
  794. page.CategoryId = nil
  795. else
  796. page.CategoryId = parentId
  797. end
  798. end
  799.  
  800. if cat then
  801. if cat.CategoryId == parentId then
  802. cat.CategoryId = nil
  803. else
  804. cat.CategoryId = parentId
  805. end
  806. end
  807.  
  808. local selectedId = self:SelectedId()
  809. self:UpdateTree()
  810. if selectedId == entryId then
  811. self:SetSelectedId( selectedId )
  812. end
  813. end
  814.  
  815. function AngryNotes:UpdateContents(id, value)
  816. local page = self:Get(id)
  817. if not page then return end
  818.  
  819. local new_content = value:gsub('^%s+', ''):gsub('%s+$', '')
  820. local contents_updated = new_content ~= page.Contents
  821. page.Contents = new_content
  822.  
  823. self:UpdateSelected(true)
  824. if AngryNotes_State.displayed == id then
  825. self:UpdateDisplayed()
  826. self:ShowDisplay()
  827. end
  828. end
  829.  
  830. function AngryNotes:ClearDisplayed()
  831. AngryNotes_State.displayed = nil
  832. self:UpdateDisplayed()
  833. self:UpdateTree()
  834. end
  835.  
  836. -------------
  837. -- Displaying Page --
  838. ---------------------
  839.  
  840. local function DragHandle_MouseDown(frame) frame:GetParent():GetParent():StartSizing("RIGHT") end
  841. local function DragHandle_MouseUp(frame)
  842. local display = frame:GetParent():GetParent()
  843. display:StopMovingOrSizing()
  844. AngryNotes_State.display.width = display:GetWidth()
  845. lwin.SavePosition(display)
  846. AngryNotes:UpdateBackdrop()
  847. end
  848. local function Mover_MouseDown(frame) frame:GetParent():StartMoving() end
  849. local function Mover_MouseUp(frame)
  850. local display = frame:GetParent()
  851. display:StopMovingOrSizing()
  852. lwin.SavePosition(display)
  853. end
  854.  
  855. function AngryNotes:ResetPosition()
  856. AngryNotes_State.display = {}
  857. AngryNotes_State.directionUp = false
  858. AngryNotes_State.locked = false
  859.  
  860. self.display_text:Show()
  861. self.mover:Show()
  862. self.frame:SetWidth(300)
  863.  
  864. lwin.RegisterConfig(self.frame, AngryNotes_State.display)
  865. lwin.RestorePosition(self.frame)
  866.  
  867. self:UpdateDirection()
  868. end
  869.  
  870. function AngryNotes_ToggleDisplay()
  871. AngryNotes:ToggleDisplay()
  872. end
  873.  
  874. function AngryNotes:ShowDisplay()
  875. self.display_text:Show()
  876. self:UpdateBackdrop()
  877. AngryNotes_State.display.hidden = false
  878. end
  879.  
  880. function AngryNotes:HideDisplay()
  881. self.display_text:Hide()
  882. AngryNotes_State.display.hidden = true
  883. end
  884.  
  885. function AngryNotes:ToggleDisplay()
  886. if self.display_text:IsShown() then
  887. self:HideDisplay()
  888. else
  889. self:ShowDisplay()
  890. end
  891. end
  892.  
  893.  
  894. function AngryNotes:CreateDisplay()
  895. local frame = CreateFrame("Frame", nil, UIParent)
  896. frame:SetPoint("CENTER",0,0)
  897. frame:SetWidth(AngryNotes_State.display.width or 300)
  898. frame:SetHeight(1)
  899. frame:SetMovable(true)
  900. frame:SetResizable(true)
  901. frame:SetClampedToScreen(true)
  902. frame:SetResizeBounds(180, 1, 830, 1)
  903. frame:SetFrameStrata("MEDIUM")
  904. self.frame = frame
  905.  
  906. lwin.RegisterConfig(frame, AngryNotes_State.display)
  907. lwin.RestorePosition(frame)
  908.  
  909. local text = CreateFrame("ScrollingMessageFrame", nil, frame)
  910. text:SetIndentedWordWrap(true)
  911. text:SetJustifyH("LEFT")
  912. text:SetFading(false)
  913. text:SetMaxLines(70)
  914. text:SetHeight(700)
  915. text:SetHyperlinksEnabled(false)
  916. self.display_text = text
  917.  
  918. local backdrop = text:CreateTexture()
  919. backdrop:SetDrawLayer("BACKGROUND")
  920. self.backdrop = backdrop
  921.  
  922. local mover = CreateFrame("Frame", nil, frame, BackdropTemplateMixin and "BackdropTemplate" or nil)
  923. mover:SetPoint("LEFT",0,0)
  924. mover:SetPoint("RIGHT",0,0)
  925. mover:SetHeight(16)
  926. mover:EnableMouse(true)
  927. mover:SetBackdrop({ bgFile = "Interface\\Tooltips\\UI-Tooltip-Background" })
  928. mover:SetBackdropColor( 0.616, 0.149, 0.114, 0.9)
  929. mover:SetScript("OnMouseDown", Mover_MouseDown)
  930. mover:SetScript("OnMouseUp", Mover_MouseUp)
  931. self.mover = mover
  932. if AngryNotes_State.locked then mover:Hide() end
  933.  
  934. local label = mover:CreateFontString()
  935. label:SetFontObject("GameFontNormal")
  936. label:SetJustifyH("CENTER")
  937. label:SetPoint("LEFT", 38, 0)
  938. label:SetPoint("RIGHT", -38, 0)
  939. label:SetText("Angry Notes")
  940.  
  941. local direction = CreateFrame("Button", nil, mover)
  942. direction:SetPoint("LEFT", 2, 0)
  943. direction:SetWidth(16)
  944. direction:SetHeight(16)
  945. direction:SetNormalTexture("Interface\\Buttons\\UI-Panel-QuestHideButton")
  946. direction:SetPushedTexture("Interface\\Buttons\\UI-Panel-QuestHideButton")
  947. direction:SetHighlightTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Highlight", "ADD")
  948. direction:SetScript("OnClick", function() AngryNotes:ToggleDirection() end)
  949. self.direction_button = direction
  950.  
  951. local lock = CreateFrame("Button", nil, mover)
  952. lock:SetNormalTexture("Interface\\LFGFRAME\\UI-LFG-ICON-LOCK")
  953. lock:GetNormalTexture():SetTexCoord(0, 0.71875, 0, 0.875)
  954. lock:SetPoint("LEFT", direction, "RIGHT", 4, 0)
  955. lock:SetWidth(12)
  956. lock:SetHeight(14)
  957. lock:SetScript("OnClick", function() AngryNotes:ToggleLock() end)
  958.  
  959. local drag = CreateFrame("Frame", nil, mover)
  960. drag:SetFrameLevel(mover:GetFrameLevel() + 10)
  961. drag:SetWidth(16)
  962. drag:SetHeight(16)
  963. drag:SetPoint("BOTTOMRIGHT", 0, 0)
  964. drag:EnableMouse(true)
  965. drag:SetScript("OnMouseDown", DragHandle_MouseDown)
  966. drag:SetScript("OnMouseUp", DragHandle_MouseUp)
  967. drag:SetAlpha(0.5)
  968. local dragtex = drag:CreateTexture(nil, "OVERLAY")
  969. dragtex:SetTexture("Interface\\AddOns\\AngryNotes\\Textures\\draghandle")
  970. dragtex:SetWidth(16)
  971. dragtex:SetHeight(16)
  972. dragtex:SetBlendMode("ADD")
  973. dragtex:SetPoint("CENTER", drag)
  974.  
  975. if AngryNotes_State.display.hidden then text:Hide() end
  976. self:UpdateMedia()
  977. self:UpdateDirection()
  978. end
  979.  
  980. function AngryNotes:ToggleLock()
  981. AngryNotes_State.locked = not AngryNotes_State.locked
  982. if AngryNotes_State.locked then
  983. self.mover:Hide()
  984. else
  985. self.mover:Show()
  986. end
  987. end
  988.  
  989. function AngryNotes:ToggleDirection()
  990. AngryNotes_State.directionUp = not AngryNotes_State.directionUp
  991. self:UpdateDirection()
  992. end
  993.  
  994. function AngryNotes:UpdateDirection()
  995. if AngryNotes_State.directionUp then
  996. self.display_text:ClearAllPoints()
  997. self.display_text:SetPoint("BOTTOMLEFT", 0, 8)
  998. self.display_text:SetPoint("RIGHT", 0, 0)
  999. self.display_text:SetInsertMode(SCROLLING_MESSAGE_FRAME_INSERT_MODE_BOTTOM)
  1000. self.direction_button:GetNormalTexture():SetTexCoord(0, 0.5, 0.5, 1)
  1001. self.direction_button:GetPushedTexture():SetTexCoord(0.5, 1, 0.5, 1)
  1002. else
  1003. self.display_text:ClearAllPoints()
  1004. self.display_text:SetPoint("TOPLEFT", 0, -8)
  1005. self.display_text:SetPoint("RIGHT", 0, 0)
  1006. self.display_text:SetInsertMode(SCROLLING_MESSAGE_FRAME_INSERT_MODE_TOP)
  1007. self.direction_button:GetNormalTexture():SetTexCoord(0, 0.5, 0, 0.5)
  1008. self.direction_button:GetPushedTexture():SetTexCoord(0.5, 1, 0, 0.5)
  1009. end
  1010. if self.display_text:IsShown() then
  1011. self.display_text:Hide()
  1012. self.display_text:Show()
  1013. end
  1014. self:UpdateDisplayed()
  1015. end
  1016.  
  1017. function AngryNotes:UpdateBackdrop()
  1018. local first, last
  1019. for lineIndex, visibleLine in ipairs(self.display_text.visibleLines) do
  1020. local messageInfo = self.display_text.historyBuffer:GetEntryAtIndex(lineIndex)
  1021. if messageInfo then
  1022. if not first then first = visibleLine end
  1023. last = visibleLine
  1024. end
  1025. end
  1026.  
  1027. if first and last and self:GetConfig('backdropShow') then
  1028. self.backdrop:ClearAllPoints()
  1029. if AngryNotes_State.directionUp then
  1030. self.backdrop:SetPoint("TOPLEFT", last, "TOPLEFT", -4, 4)
  1031. self.backdrop:SetPoint("BOTTOMRIGHT", first, "BOTTOMRIGHT", 4, -4)
  1032. else
  1033. self.backdrop:SetPoint("TOPLEFT", first, "TOPLEFT", -4, 4)
  1034. self.backdrop:SetPoint("BOTTOMRIGHT", last, "BOTTOMRIGHT", 4, -4)
  1035. end
  1036. self.backdrop:SetColorTexture( HexToRGB(self:GetConfig('backdropColor')) )
  1037. self.backdrop:Show()
  1038. else
  1039. self.backdrop:Hide()
  1040. end
  1041. end
  1042.  
  1043. local editFontName, editFontHeight, editFontFlags
  1044. function AngryNotes:UpdateMedia()
  1045. local fontName = LSM:Fetch("font", AngryNotes:GetConfig('fontName'))
  1046. local fontHeight = AngryNotes:GetConfig('fontHeight')
  1047. local fontFlags = AngryNotes:GetConfig('fontFlags')
  1048.  
  1049. self.display_text:SetTextColor( HexToRGB(self:GetConfig('color')) )
  1050. self.display_text:SetFont(fontName, fontHeight, fontFlags)
  1051. self.display_text:SetSpacing( AngryNotes:GetConfig('lineSpacing') )
  1052.  
  1053. if self.window then
  1054. if self:GetConfig('editBoxFont') then
  1055. if not editFontName then
  1056. editFontName, editFontHeight, editFontFlags = self.window.text.editBox:GetFont()
  1057. end
  1058. self.window.text.editBox:SetFont(fontName, fontHeight, fontFlags)
  1059. elseif editFontName then
  1060. self.window.text.editBox:SetFont(editFontName, editFontHeight, editFontFlags)
  1061. end
  1062. end
  1063.  
  1064. self:UpdateBackdrop()
  1065. end
  1066.  
  1067. local function ci_pattern(pattern)
  1068. local p = pattern:gsub("(%%?)(.)", function(percent, letter)
  1069. if percent ~= "" or not letter:match("%a") then
  1070. return percent .. letter
  1071. else
  1072. return string.format("[%s%s]", letter:lower(), letter:upper())
  1073. end
  1074. end)
  1075. return p
  1076. end
  1077.  
  1078. function AngryNotes:UpdateDisplayedIfNewGroup()
  1079. local newGroup = self:GetCurrentGroup()
  1080. if newGroup ~= currentGroup then
  1081. currentGroup = newGroup
  1082. self:UpdateDisplayed()
  1083. end
  1084. end
  1085.  
  1086. function AngryNotes:UpdateDisplayed()
  1087. local page = AngryNotes_Pages[ AngryNotes_State.displayed ]
  1088. if page then
  1089. local text = page.Contents
  1090.  
  1091. local highlights = { }
  1092. for token in string.gmatch( AngryNotes:GetConfig('highlight') , "[^%s%p]+") do
  1093. token = token:lower()
  1094. if token == 'group'then
  1095. tinsert(highlights, 'g'..(currentGroup or 0))
  1096. else
  1097. tinsert(highlights, token)
  1098. end
  1099. end
  1100. local highlightHex = self:GetConfig('highlightColor')
  1101.  
  1102. text = text:gsub("||", "|")
  1103. :gsub(ci_pattern('|cblue'), "|cff00cbf4")
  1104. :gsub(ci_pattern('|cgreen'), "|cff0adc00")
  1105. :gsub(ci_pattern('|cred'), "|cffeb310c")
  1106. :gsub(ci_pattern('|cyellow'), "|cfffaf318")
  1107. :gsub(ci_pattern('|corange'), "|cffff9d00")
  1108. :gsub(ci_pattern('|cpink'), "|cfff64c97")
  1109. :gsub(ci_pattern('|cpurple'), "|cffdc44eb")
  1110. :gsub(ci_pattern('|cdeathknight'), "|cffc41f3b")
  1111. :gsub(ci_pattern('|cdruid'), "|cffff7d0a")
  1112. :gsub(ci_pattern('|chunter'), "|cffabd473")
  1113. :gsub(ci_pattern('|cmage'), "|cff69ccf0")
  1114. :gsub(ci_pattern('|cmonk'), "|cff00ff96")
  1115. :gsub(ci_pattern('|cpaladin'), "|cfff58cba")
  1116. :gsub(ci_pattern('|cpriest'), "|cffffffff")
  1117. :gsub(ci_pattern('|crogue'), "|cfffff569")
  1118. :gsub(ci_pattern('|cshaman'), "|cff0070de")
  1119. :gsub(ci_pattern('|cwarlock'), "|cff9482c9")
  1120. :gsub(ci_pattern('|cwarrior'), "|cffc79c6e")
  1121. :gsub(ci_pattern('|cdemonhunter'), "|cffa330c9")
  1122. :gsub("([^%s%p]+)", function(word)
  1123. local word_lower = word:lower()
  1124. for _, token in ipairs(highlights) do
  1125. if token == word_lower then
  1126. return string.format("|cff%s%s|r", highlightHex, word)
  1127. end
  1128. end
  1129. return word
  1130. end)
  1131. :gsub(ci_pattern('{spell%s+(%d+)}'), function(id)
  1132. return GetSpellLink(id)
  1133. end)
  1134. :gsub(ci_pattern('{boss%s+(%d+)}'), function(id)
  1135. return select(5, EJ_GetEncounterInfo(id))
  1136. end)
  1137. :gsub(ci_pattern('{journal%s+(%d+)}'), function(id)
  1138. return C_EncounterJournal.GetSectionInfo(id) and C_EncounterJournal.GetSectionInfo(id).link
  1139. end)
  1140. :gsub(ci_pattern('{star}'), "{rt1}")
  1141. :gsub(ci_pattern('{circle}'), "{rt2}")
  1142. :gsub(ci_pattern('{diamond}'), "{rt3}")
  1143. :gsub(ci_pattern('{triangle}'), "{rt4}")
  1144. :gsub(ci_pattern('{moon}'), "{rt5}")
  1145. :gsub(ci_pattern('{square}'), "{rt6}")
  1146. :gsub(ci_pattern('{cross}'), "{rt7}")
  1147. :gsub(ci_pattern('{x}'), "{rt7}")
  1148. :gsub(ci_pattern('{skull}'), "{rt8}")
  1149. :gsub(ci_pattern('{rt([1-8])}'), "|TInterface\\TargetingFrame\\UI-RaidTargetingIcon_%1:0|t" )
  1150. :gsub(ci_pattern('{healthstone}'), "{hs}")
  1151. :gsub(ci_pattern('{hs}'), "|TInterface\\Icons\\INV_Stone_04:0|t")
  1152. :gsub(ci_pattern('{bloodlust}'), "{bl}")
  1153. :gsub(ci_pattern('{bl}'), "|TInterface\\Icons\\SPELL_Nature_Bloodlust:0|t")
  1154. :gsub(ci_pattern('{icon%s+(%d+)}'), function(id)
  1155. return format("|T%s:0|t", select(3, GetSpellInfo(tonumber(id))) )
  1156. end)
  1157. :gsub(ci_pattern('{icon%s+([%w_]+)}'), "|TInterface\\Icons\\%1:0|t")
  1158. :gsub(ci_pattern('{damage}'), "{dps}")
  1159. :gsub(ci_pattern('{tank}'), "|TInterface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES:0:0:0:0:64:64:0:19:22:41|t")
  1160. :gsub(ci_pattern('{healer}'), "|TInterface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES:0:0:0:0:64:64:20:39:1:20|t")
  1161. :gsub(ci_pattern('{dps}'), "|TInterface\\LFGFrame\\UI-LFG-ICON-PORTRAITROLES:0:0:0:0:64:64:20:39:22:41|t")
  1162. :gsub(ci_pattern('{hero}'), "{heroism}")
  1163. :gsub(ci_pattern('{heroism}'), "|TInterface\\Icons\\ABILITY_Shaman_Heroism:0|t")
  1164. :gsub(ci_pattern('{hunter}'), "|TInterface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES:0:0:0:0:64:64:0:16:16:32|t")
  1165. :gsub(ci_pattern('{warrior}'), "|TInterface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES:0:0:0:0:64:64:0:16:0:16|t")
  1166. :gsub(ci_pattern('{rogue}'), "|TInterface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES:0:0:0:0:64:64:32:48:0:16|t")
  1167. :gsub(ci_pattern('{mage}'), "|TInterface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES:0:0:0:0:64:64:16:32:0:16|t")
  1168. :gsub(ci_pattern('{priest}'), "|TInterface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES:0:0:0:0:64:64:32:48:16:32|t")
  1169. :gsub(ci_pattern('{warlock}'), "|TInterface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES:0:0:0:0:64:64:48:64:16:32|t")
  1170. :gsub(ci_pattern('{paladin}'), "|TInterface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES:0:0:0:0:64:64:0:16:32:48|t")
  1171. :gsub(ci_pattern('{deathknight}'), "|TInterface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES:0:0:0:0:64:64:16:32:32:48|t")
  1172. :gsub(ci_pattern('{druid}'), "|TInterface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES:0:0:0:0:64:64:48:64:0:16|t")
  1173. :gsub(ci_pattern('{monk}'), "|TInterface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES:0:0:0:0:64:64:32:48:32:48|t")
  1174. :gsub(ci_pattern('{shaman}'), "|TInterface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES:0:0:0:0:64:64:16:32:16:32|t")
  1175. :gsub(ci_pattern('{demonhunter}'), "|TInterface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES:0:0:0:0:64:64:64:48:32:48|t")
  1176.  
  1177. self.display_text:Clear()
  1178. local lines = { strsplit("\n", text) }
  1179. local lines_count = #lines
  1180. for i = 1, lines_count do
  1181. local line
  1182. if AngryNotes_State.directionUp then
  1183. line = lines[i]
  1184. else
  1185. line = lines[lines_count - i + 1]
  1186. end
  1187. if line == "" then line = " " end
  1188. self.display_text:AddMessage(line)
  1189. end
  1190. else
  1191. self.display_text:Clear()
  1192. end
  1193. self:UpdateBackdrop()
  1194. end
  1195.  
  1196. function AngryNotes_OutputDisplayed()
  1197. return AngryNotes:OutputDisplayed( AngryNotes:SelectedId() )
  1198. end
  1199. function AngryNotes:OutputDisplayed(id)
  1200. if not id then id = AngryNotes_State.displayed end
  1201. local page = AngryNotes_Pages[ id ]
  1202. local channel
  1203. if IsInGroup(LE_PARTY_CATEGORY_INSTANCE) or IsInRaid(LE_PARTY_CATEGORY_INSTANCE) then
  1204. channel = "INSTANCE_CHAT"
  1205. elseif IsInRaid() then
  1206. channel = "RAID"
  1207. elseif IsInGroup() then
  1208. channel = "PARTY"
  1209. end
  1210. if channel and page then
  1211. local output = page.Contents
  1212.  
  1213. output = output:gsub("||", "|")
  1214. :gsub(ci_pattern('|r'), "")
  1215. :gsub(ci_pattern('|cblue'), "")
  1216. :gsub(ci_pattern('|cgreen'), "")
  1217. :gsub(ci_pattern('|cred'), "")
  1218. :gsub(ci_pattern('|cyellow'), "")
  1219. :gsub(ci_pattern('|corange'), "")
  1220. :gsub(ci_pattern('|cpink'), "")
  1221. :gsub(ci_pattern('|cpurple'), "")
  1222. :gsub(ci_pattern('|cdeathknight'), "")
  1223. :gsub(ci_pattern('|cdruid'), "")
  1224. :gsub(ci_pattern('|chunter'), "")
  1225. :gsub(ci_pattern('|cmage'), "")
  1226. :gsub(ci_pattern('|cmonk'), "")
  1227. :gsub(ci_pattern('|cpaladin'), "")
  1228. :gsub(ci_pattern('|cpriest'), "")
  1229. :gsub(ci_pattern('|crogue'), "")
  1230. :gsub(ci_pattern('|cshaman'), "")
  1231. :gsub(ci_pattern('|cwarlock'), "")
  1232. :gsub(ci_pattern('|cwarrior'), "")
  1233. :gsub(ci_pattern('|cdemonhunter'), "")
  1234. :gsub(ci_pattern('|c%w?%w?%w?%w?%w?%w?%w?%w?'), "")
  1235. :gsub(ci_pattern('{spell%s+(%d+)}'), function(id)
  1236. return GetSpellLink(id)
  1237. end)
  1238. :gsub(ci_pattern('{boss%s+(%d+)}'), function(id)
  1239. return select(5, EJ_GetEncounterInfo(id))
  1240. end)
  1241. :gsub(ci_pattern('{journal%s+(%d+)}'), function(id)
  1242. return C_EncounterJournal.GetSectionInfo(id) and C_EncounterJournal.GetSectionInfo(id).link
  1243. end)
  1244. :gsub(ci_pattern('{star}'), "{rt1}")
  1245. :gsub(ci_pattern('{circle}'), "{rt2}")
  1246. :gsub(ci_pattern('{diamond}'), "{rt3}")
  1247. :gsub(ci_pattern('{triangle}'), "{rt4}")
  1248. :gsub(ci_pattern('{moon}'), "{rt5}")
  1249. :gsub(ci_pattern('{square}'), "{rt6}")
  1250. :gsub(ci_pattern('{cross}'), "{rt7}")
  1251. :gsub(ci_pattern('{x}'), "{rt7}")
  1252. :gsub(ci_pattern('{skull}'), "{rt8}")
  1253. :gsub(ci_pattern('{healthstone}'), "{hs}")
  1254. :gsub(ci_pattern('{hs}'), 'Healthstone')
  1255. :gsub(ci_pattern('{bloodlust}'), "{bl}")
  1256. :gsub(ci_pattern('{bl}'), 'Bloodlust')
  1257. :gsub(ci_pattern('{icon%s+([%w_]+)}'), '')
  1258. :gsub(ci_pattern('{damage}'), 'Damage')
  1259. :gsub(ci_pattern('{tank}'), 'Tanks')
  1260. :gsub(ci_pattern('{healer}'), 'Healers')
  1261. :gsub(ci_pattern('{dps}'), 'Damage')
  1262. :gsub(ci_pattern('{hero}'), "{heroism}")
  1263. :gsub(ci_pattern('{heroism}'), 'Heroism')
  1264. :gsub(ci_pattern('{hunter}'), LOCALIZED_CLASS_NAMES_MALE["HUNTER"])
  1265. :gsub(ci_pattern('{warrior}'), LOCALIZED_CLASS_NAMES_MALE["WARRIOR"])
  1266. :gsub(ci_pattern('{rogue}'), LOCALIZED_CLASS_NAMES_MALE["ROGUE"])
  1267. :gsub(ci_pattern('{mage}'), LOCALIZED_CLASS_NAMES_MALE["MAGE"])
  1268. :gsub(ci_pattern('{priest}'), LOCALIZED_CLASS_NAMES_MALE["PRIEST"])
  1269. :gsub(ci_pattern('{warlock}'), LOCALIZED_CLASS_NAMES_MALE["WARLOCK"])
  1270. :gsub(ci_pattern('{paladin}'), LOCALIZED_CLASS_NAMES_MALE["PALADIN"])
  1271. :gsub(ci_pattern('{deathknight}'), LOCALIZED_CLASS_NAMES_MALE["DEATHKNIGHT"])
  1272. :gsub(ci_pattern('{druid}'), LOCALIZED_CLASS_NAMES_MALE["DRUID"])
  1273. :gsub(ci_pattern('{monk}'), LOCALIZED_CLASS_NAMES_MALE["MONK"])
  1274. :gsub(ci_pattern('{shaman}'), LOCALIZED_CLASS_NAMES_MALE["SHAMAN"])
  1275. :gsub(ci_pattern('{demonhunter}'), LOCALIZED_CLASS_NAMES_MALE["DEMONHUNTER"])
  1276.  
  1277. local lines = { strsplit("\n", output) }
  1278. for _, line in ipairs(lines) do
  1279. if line ~= "" then
  1280. SendChatMessage(line, channel)
  1281. end
  1282. end
  1283. end
  1284. end
  1285.  
  1286. -----------------
  1287. -- Addon Setup --
  1288. -----------------
  1289.  
  1290. local configDefaults = {
  1291. scale = 1,
  1292. hideoncombat = false,
  1293. fontName = "Friz Quadrata TT",
  1294. fontHeight = 12,
  1295. fontFlags = "",
  1296. highlight = "",
  1297. highlightColor = "ffd200",
  1298. color = "ffffff",
  1299. lineSpacing = 0,
  1300. backdropShow = false,
  1301. backdropColor = "00000080",
  1302. editBoxFont = false,
  1303. }
  1304.  
  1305. function AngryNotes:GetConfig(key)
  1306. if AngryNotes_Config[key] == nil then
  1307. return configDefaults[key]
  1308. else
  1309. return AngryNotes_Config[key]
  1310. end
  1311. end
  1312.  
  1313. function AngryNotes:SetConfig(key, value)
  1314. if configDefaults[key] == value then
  1315. AngryNotes_Config[key] = nil
  1316. else
  1317. AngryNotes_Config[key] = value
  1318. end
  1319. end
  1320.  
  1321. function AngryNotes:RestoreDefaults()
  1322. AngryNotes_Config = {}
  1323. self:UpdateMedia()
  1324. self:UpdateDisplayed()
  1325. LibStub("AceConfigRegistry-3.0"):NotifyChange("AngryNotes")
  1326. end
  1327.  
  1328. local blizOptionsPanel
  1329. function AngryNotes:OnInitialize()
  1330. if AngryNotes_State == nil then
  1331. AngryNotes_State = { tree = {}, window = {}, display = {}, displayed = nil, locked = false, directionUp = false }
  1332. end
  1333. if AngryNotes_Pages == nil then AngryNotes_Pages = { } end
  1334. if AngryNotes_Config == nil then AngryNotes_Config = { } end
  1335. if AngryNotes_Categories == nil then
  1336. AngryNotes_Categories = { }
  1337. else
  1338. for _, cat in pairs(AngryNotes_Categories) do
  1339. if cat.Children then
  1340. for _, pageId in ipairs(cat.Children) do
  1341. local page = AngryNotes_Pages[pageId]
  1342. if page then
  1343. page.CategoryId = cat.Id
  1344. end
  1345. end
  1346. cat.Children = nil
  1347. end
  1348. end
  1349. end
  1350.  
  1351. local ver = AngryNotes_Version
  1352. if ver:sub(1,1) == "@" then ver = "dev" end
  1353.  
  1354. local options = {
  1355. name = "Angry Notes "..ver,
  1356. handler = AngryNotes,
  1357. type = "group",
  1358. args = {
  1359. window = {
  1360. type = "execute",
  1361. order = 3,
  1362. name = "Toggle Window",
  1363. desc = "Shows/hides the edit window (also available in game keybindings)",
  1364. func = function() AngryNotes_ToggleWindow() end
  1365. },
  1366. help = {
  1367. type = "execute",
  1368. order = 99,
  1369. name = "Help",
  1370. hidden = true,
  1371. func = function()
  1372. LibStub("AceConfigCmd-3.0").HandleCommand(self, "aa", "AngryNotes", "")
  1373. end
  1374. },
  1375. toggle = {
  1376. type = "execute",
  1377. order = 1,
  1378. name = "Toggle Display",
  1379. desc = "Shows/hides the display frame (also available in game keybindings)",
  1380. func = function() AngryNotes_ToggleDisplay() end
  1381. },
  1382. deleteall = {
  1383. type = "execute",
  1384. name = "Delete All Pages",
  1385. desc = "Deletes all pages",
  1386. order = 4,
  1387. hidden = true,
  1388. cmdHidden = false,
  1389. confirm = true,
  1390. func = function()
  1391. AngryNotes_State.displayed = nil
  1392. AngryNotes_Pages = {}
  1393. AngryNotes_Categories = {}
  1394. self:UpdateTree()
  1395. self:UpdateSelected()
  1396. self:UpdateDisplayed()
  1397. if self.window then self.window.tree:SetSelected(nil) end
  1398. self:Print("All pages have been deleted.")
  1399. end
  1400. },
  1401. defaults = {
  1402. type = "execute",
  1403. name = "Restore Defaults",
  1404. desc = "Restore configuration values to their default settings",
  1405. order = 10,
  1406. hidden = true,
  1407. cmdHidden = false,
  1408. confirm = true,
  1409. func = function()
  1410. self:RestoreDefaults()
  1411. end
  1412. },
  1413. output = {
  1414. type = "execute",
  1415. name = "Output",
  1416. desc = "Outputs currently displayed notes to chat",
  1417. order = 11,
  1418. hidden = true,
  1419. cmdHidden = false,
  1420. confirm = true,
  1421. func = function()
  1422. self:OutputDisplayed()
  1423. end
  1424. },
  1425. send = {
  1426. type = "input",
  1427. name = "Display",
  1428. desc = "Display page with specified name",
  1429. order = 12,
  1430. hidden = true,
  1431. cmdHidden = false,
  1432. confirm = true,
  1433. get = function(info) return "" end,
  1434. set = function(info, val)
  1435. local result = self:DisplayPageByName( val:trim() )
  1436. if result == false then
  1437. self:Print( RED_FONT_COLOR_CODE .. "A page with the name \""..val:trim().."\" could not be found.|r" )
  1438. elseif not result then
  1439. self:Print( RED_FONT_COLOR_CODE .. "You don't have permission to send a page.|r" )
  1440. end
  1441. end
  1442. },
  1443. clear = {
  1444. type = "execute",
  1445. name = "Clear",
  1446. desc = "Clears currently displayed page",
  1447. order = 13,
  1448. hidden = true,
  1449. cmdHidden = false,
  1450. confirm = true,
  1451. func = function()
  1452. AngryNotes_ClearPage()
  1453. end
  1454. },
  1455. resetposition = {
  1456. type = "execute",
  1457. order = 22,
  1458. name = "Reset Position",
  1459. desc = "Resets position for the note display",
  1460. func = function()
  1461. self:ResetPosition()
  1462. end
  1463. },
  1464. lock = {
  1465. type = "execute",
  1466. order = 2,
  1467. name = "Toggle Lock",
  1468. desc = "Shows/hides the display mover (also available in game keybindings)",
  1469. func = function() self:ToggleLock() end
  1470. },
  1471. config = {
  1472. type = "group",
  1473. order = 5,
  1474. name = "General",
  1475. inline = true,
  1476. args = {
  1477. highlight = {
  1478. type = "input",
  1479. order = 1,
  1480. name = "Highlight",
  1481. desc = "A list of words to highlight on displayed pages (separated by spaces or punctuation)\n\nUse 'Group' to highlight the current group you are in, ex. G2",
  1482. get = function(info) return self:GetConfig('highlight') end,
  1483. set = function(info, val)
  1484. self:SetConfig('highlight', val)
  1485. self:UpdateDisplayed()
  1486. end
  1487. },
  1488. hideoncombat = {
  1489. type = "toggle",
  1490. order = 3,
  1491. name = "Hide on Combat",
  1492. desc = "Enable to hide display frame upon entering combat",
  1493. get = function(info) return self:GetConfig('hideoncombat') end,
  1494. set = function(info, val)
  1495. self:SetConfig('hideoncombat', val)
  1496.  
  1497. end
  1498. },
  1499. scale = {
  1500. type = "range",
  1501. order = 4,
  1502. name = "Scale",
  1503. desc = "Sets the scale of the edit window",
  1504. min = 0.3,
  1505. max = 3,
  1506. get = function(info) return self:GetConfig('scale') end,
  1507. set = function(info, val)
  1508. self:SetConfig('scale', val)
  1509. if AngryNotes.window then AngryNotes.window.frame:SetScale(val) end
  1510. end
  1511. },
  1512. backdrop = {
  1513. type = "toggle",
  1514. order = 5,
  1515. name = "Display Backdrop",
  1516. desc = "Enable to display a backdrop behind the note display",
  1517. get = function(info) return self:GetConfig('backdropShow') end,
  1518. set = function(info, val)
  1519. self:SetConfig('backdropShow', val)
  1520. self:UpdateBackdrop()
  1521. end
  1522. },
  1523. backdropcolor = {
  1524. type = "color",
  1525. order = 6,
  1526. name = "Backdrop Color",
  1527. desc = "The color used by the backdrop",
  1528. hasAlpha = true,
  1529. get = function(info)
  1530. local hex = self:GetConfig('backdropColor')
  1531. return HexToRGB(hex)
  1532. end,
  1533. set = function(info, r, g, b, a)
  1534. self:SetConfig('backdropColor', RGBToHex(r, g, b, a))
  1535. self:UpdateMedia()
  1536. self:UpdateDisplayed()
  1537. end
  1538. },
  1539. }
  1540. },
  1541. font = {
  1542. type = "group",
  1543. order = 6,
  1544. name = "Font",
  1545. inline = true,
  1546. args = {
  1547. fontname = {
  1548. type = 'select',
  1549. order = 1,
  1550. dialogControl = 'LSM30_Font',
  1551. name = 'Face',
  1552. desc = 'Sets the font face used to display a page',
  1553. values = LSM:HashTable("font"),
  1554. get = function(info) return self:GetConfig('fontName') end,
  1555. set = function(info, val)
  1556. self:SetConfig('fontName', val)
  1557. self:UpdateMedia()
  1558. end
  1559. },
  1560. fontheight = {
  1561. type = "range",
  1562. order = 2,
  1563. name = "Size",
  1564. desc = function()
  1565. return "Sets the font height used to display a page"
  1566. end,
  1567. min = 6,
  1568. max = 24,
  1569. step = 1,
  1570. get = function(info) return self:GetConfig('fontHeight') end,
  1571. set = function(info, val)
  1572. self:SetConfig('fontHeight', val)
  1573. self:UpdateMedia()
  1574. end
  1575. },
  1576. fontflags = {
  1577. type = "select",
  1578. order = 3,
  1579. name = "Outline",
  1580. desc = "Sets the font outline used to display a page",
  1581. values = { ["NONE"] = "None", ["OUTLINE"] = "Outline", ["THICKOUTLINE"] = "Thick Outline", ["MONOCHROMEOUTLINE"] = "Monochrome" },
  1582. get = function(info) return self:GetConfig('fontFlags') end,
  1583. set = function(info, val)
  1584. self:SetConfig('fontFlags', val)
  1585. self:UpdateMedia()
  1586. end
  1587. },
  1588. color = {
  1589. type = "color",
  1590. order = 4,
  1591. name = "Normal Color",
  1592. desc = "The normal color used to display notes",
  1593. get = function(info)
  1594. local hex = self:GetConfig('color')
  1595. return HexToRGB(hex)
  1596. end,
  1597. set = function(info, r, g, b)
  1598. self:SetConfig('color', RGBToHex(r, g, b))
  1599. self:UpdateMedia()
  1600. self:UpdateDisplayed()
  1601. end
  1602. },
  1603. highlightcolor = {
  1604. type = "color",
  1605. order = 5,
  1606. name = "Highlight Color",
  1607. desc = "The color used to emphasize highlighted words",
  1608. get = function(info)
  1609. local hex = self:GetConfig('highlightColor')
  1610. return HexToRGB(hex)
  1611. end,
  1612. set = function(info, r, g, b)
  1613. self:SetConfig('highlightColor', RGBToHex(r, g, b))
  1614. self:UpdateDisplayed()
  1615. end
  1616. },
  1617. linespacing = {
  1618. type = "range",
  1619. order = 6,
  1620. name = "Line Spacing",
  1621. desc = function()
  1622. return "Sets the line spacing used to display a page"
  1623. end,
  1624. min = 0,
  1625. max = 10,
  1626. step = 1,
  1627. get = function(info) return self:GetConfig('lineSpacing') end,
  1628. set = function(info, val)
  1629. self:SetConfig('lineSpacing', val)
  1630. self:UpdateMedia()
  1631. self:UpdateDisplayed()
  1632. end
  1633. },
  1634. editBoxFont = {
  1635. type = "toggle",
  1636. order = 7,
  1637. name = "Change Edit Box Font",
  1638. desc = "Enable to set edit box font to display font",
  1639. get = function(info) return self:GetConfig('editBoxFont') end,
  1640. set = function(info, val)
  1641. self:SetConfig('editBoxFont', val)
  1642. self:UpdateMedia()
  1643. end
  1644. },
  1645. }
  1646. },
  1647. }
  1648. }
  1649.  
  1650. self:RegisterChatCommand("an", "ChatCommand")
  1651. LibStub("AceConfig-3.0"):RegisterOptionsTable("AngryNotes", options)
  1652.  
  1653. blizOptionsPanel = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("AngryNotes", "Angry Notes")
  1654. blizOptionsPanel.default = function() self:RestoreDefaults() end
  1655. end
  1656.  
  1657. function AngryNotes:ChatCommand(input)
  1658. if not input or input:trim() == "" then
  1659. AngryNotes_ToggleWindow()
  1660. elseif input:trim() == "config" then
  1661. InterfaceOptionsFrame_OpenToCategory(blizOptionsPanel)
  1662. InterfaceOptionsFrame_OpenToCategory(blizOptionsPanel)
  1663. else
  1664. LibStub("AceConfigCmd-3.0").HandleCommand(self, "an", "AngryNotes", input)
  1665. end
  1666. end
  1667.  
  1668. function AngryNotes:OnEnable()
  1669. self:CreateDisplay()
  1670. C_Timer.After(0.1, function() self:UpdateBackdrop() end)
  1671.  
  1672. self:RegisterEvent("GROUP_JOINED")
  1673. self:RegisterEvent("GROUP_ROSTER_UPDATE")
  1674.  
  1675. self:RegisterEvent("PLAYER_REGEN_DISABLED")
  1676.  
  1677. LSM.RegisterCallback(self, "LibSharedMedia_Registered", "UpdateMedia")
  1678. LSM.RegisterCallback(self, "LibSharedMedia_SetGlobal", "UpdateMedia")
  1679. end
  1680.  
  1681. function AngryNotes:GROUP_JOINED()
  1682. self:UpdateDisplayedIfNewGroup()
  1683. end
  1684.  
  1685. function AngryNotes:PLAYER_REGEN_DISABLED()
  1686. if AngryNotes:GetConfig('hideoncombat') then
  1687. self:HideDisplay()
  1688. end
  1689. end
  1690.  
  1691. function AngryNotes:GROUP_ROSTER_UPDATE()
  1692. if not (IsInRaid() or IsInGroup()) then
  1693. if AngryNotes_State.displayed then self:ClearDisplayed() end
  1694. currentGroup = nil
  1695. warnedPermission = false
  1696. else
  1697. self:UpdateDisplayedIfNewGroup()
  1698. end
  1699. end
  1700.  
Advertisement
Add Comment
Please, Sign In to add comment