├── .gitignore ├── CChatNotifier.toc ├── README.md ├── UI ├── MainUI.lua ├── MainUI_functions.lua ├── listFrame.lua └── minimapButton.lua ├── i18n ├── deDE.lua ├── enUS.lua └── loc.lua ├── images ├── found.png └── ui.png ├── img ├── bar.blp ├── grabber.blp ├── grabber_s.blp ├── iclose.blp ├── iplus.blp ├── logo.blp ├── logoo.blp ├── logos.blp ├── off.blp ├── on.blp └── trash.blp ├── libs └── SettingsCreator.lua ├── main.lua └── settings.lua /.gitignore: -------------------------------------------------------------------------------- 1 | *.zip 2 | /.vscode/ -------------------------------------------------------------------------------- /CChatNotifier.toc: -------------------------------------------------------------------------------- 1 | ## Interface: 20501 2 | ## Title: CChatNotifier 3 | ## Author: coolmodi 4 | ## Version: 1.1 5 | ## Notes: Watchs chat and notifies you if it finds words you look for. 6 | ## Notes-deDE: Beobachtet Chat und benachrichtigt dich wenn es gesuchte Wörter findet. 7 | ## SavedVariablesPerCharacter: CChatNotifier_settings, CChatNotifier_data 8 | 9 | libs/SettingsCreator.lua 10 | 11 | i18n/loc.lua 12 | i18n/enUS.lua 13 | i18n/deDE.lua 14 | 15 | main.lua 16 | settings.lua 17 | UI/MainUI.lua 18 | UI/MainUI_functions.lua 19 | UI/minimapButton.lua -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CChatNotifier 2 | A WoW Classic addon that can be used to filter chat for custom keywords. It will then notify you whenever it finds them in chat messages. 3 | 4 | This is my minimalistic idea of a "LFG" addon. I don't want to look at chat 24/7 but also don't want to miss relevant messages. The more elaborate LFG addons are imho overkill, and at the same time not flexible enough, I don't need a list or anything, I just don't want to miss a message containing arbitrary things if it pops up. This solves that problem just fine, at least its ugly predecessor I had for vanilla pservers did. 5 | 6 | ## Features 7 | * Create custom keyword groups to be looked for in chat (channels, say and yell). 8 | * GUI to manage everything. 9 | * If a word is found it will notify you in chat, optionally plays a sound too. 10 | * Chat window for notification can be chosen, tab will flash when not shown. 11 | * Name in notification can be clicked to open /whisper. 12 | * Individual keyword groups or whole addon can be toggled on/off. 13 | 14 | ![The UI](images/ui.png) 15 | 16 | ![Word found](images/found.png) 17 | -------------------------------------------------------------------------------- /UI/MainUI.lua: -------------------------------------------------------------------------------- 1 | local _addonName, _addon = ...; 2 | local L = _addon:GetLocalization(); 3 | 4 | local LIST_ITEM_HEIGHT = 27; 5 | local MAX_ITEMS = 14; 6 | local MIN_ITEMS = 9; 7 | local HEIGHT_NO_CONTENT = 71; 8 | 9 | -- Main frame 10 | local frame = CreateFrame("Frame", "CCNUI_MainUI", UIParent, "ButtonFrameTemplate"); 11 | frame:SetPoint("CENTER", 0, 0); 12 | frame:SetWidth(275); 13 | frame:SetHeight(MIN_ITEMS*LIST_ITEM_HEIGHT + HEIGHT_NO_CONTENT); 14 | frame:SetResizable(true); 15 | frame:SetClampedToScreen(true); 16 | frame:SetMaxResize(400, MAX_ITEMS*LIST_ITEM_HEIGHT + HEIGHT_NO_CONTENT); 17 | frame:SetMinResize(250, MIN_ITEMS*LIST_ITEM_HEIGHT + HEIGHT_NO_CONTENT); 18 | frame:SetMovable(true); 19 | frame:EnableMouse(true); 20 | frame.TitleText:SetText(_addonName); 21 | frame.portrait:SetTexture([[Interface\AddOns\CChatNotifier\img\logo]]); 22 | frame:Hide(); 23 | 24 | ButtonFrameTemplate_HideButtonBar(frame); 25 | 26 | -- Add drag area 27 | frame.dragBar = CreateFrame("Frame", nil, frame); 28 | frame.dragBar:SetPoint("TOPLEFT"); 29 | frame.dragBar:SetPoint("BOTTOMRIGHT", frame.CloseButton, "TOPLEFT", 0, -40); 30 | frame.dragBar:SetScript("OnMouseDown", function(self) 31 | self:GetParent():StartMoving(); 32 | end); 33 | frame.dragBar:SetScript("OnMouseUp", function(self) 34 | self:GetParent():StopMovingOrSizing(); 35 | end); 36 | 37 | -- Delete button for delete all function 38 | frame.deleteBtn = CreateFrame("Button", nil, frame); 39 | frame.deleteBtn:SetSize(18, 18); 40 | frame.deleteBtn:SetPoint("TOPRIGHT", -15, -35); 41 | frame.deleteBtn:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\trash]]); 42 | frame.deleteBtn:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\trash]]); 43 | 44 | -- Add button for switching to add content 45 | frame.addBtn = CreateFrame("Button", nil, frame); 46 | frame.addBtn:SetSize(15, 15); 47 | frame.addBtn:SetPoint("RIGHT", frame.deleteBtn, "LEFT", -15, 0); 48 | frame.addBtn:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\iplus]]); 49 | frame.addBtn:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\iplus]]); 50 | 51 | -- Add button for toggling addon on/off 52 | frame.toggleBtn = CreateFrame("Button", nil, frame); 53 | frame.toggleBtn:SetSize(15, 15); 54 | frame.toggleBtn:SetPoint("RIGHT", frame.addBtn, "LEFT", -15, 0); 55 | frame.toggleBtn:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\on]]); 56 | frame.toggleBtn:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\on]]); 57 | 58 | -- Settings button 59 | frame.settingsBtn = CreateFrame("Button", nil, frame); 60 | frame.settingsBtn:SetSize(18, 18); 61 | frame.settingsBtn:SetPoint("TOPLEFT", 70, -35); 62 | frame.settingsBtn:SetNormalTexture([[interface/scenarios/scenarioicon-interact.blp]]); 63 | frame.settingsBtn:SetHighlightTexture([[interface/scenarios/scenarioicon-interact.blp]]); 64 | 65 | -- Resize knob 66 | frame.resizeBtn = CreateFrame("Button", nil, frame); 67 | frame.resizeBtn:SetSize(64, 18); 68 | frame.resizeBtn:SetPoint("TOPRIGHT", frame, "BOTTOMRIGHT", -3, 1); 69 | frame.resizeBtn:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\grabber_s]]); 70 | frame.resizeBtn:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\grabber]]); 71 | 72 | 73 | ---------------------------------------------------------------------------------------------------------------- 74 | -- Content frames 75 | ---------------------------------------------------------------------------------------------------------------- 76 | 77 | -- Scrollframe for the list 78 | frame.scrollFrame = CreateFrame("ScrollFrame", nil, frame.Inset, "FauxScrollFrameTemplate"); 79 | frame.scrollFrame:SetPoint("TOPLEFT", 3, -3); 80 | frame.scrollFrame:SetPoint("BOTTOMRIGHT", -3, 3); 81 | frame.scrollFrame.ScrollBar:ClearAllPoints(); 82 | frame.scrollFrame.ScrollBar:SetPoint("TOPRIGHT", -1, -18); 83 | frame.scrollFrame.ScrollBar:SetPoint("BOTTOMRIGHT", -1, 16); 84 | 85 | frame.scrollFrame.ScrollBarTop = frame.scrollFrame:CreateTexture(nil, "BACKGROUND"); 86 | frame.scrollFrame.ScrollBarTop:SetPoint("TOPRIGHT", 6, 2); 87 | frame.scrollFrame.ScrollBarTop:SetTexture ([[Interface\PaperDollInfoFrame\UI-Character-ScrollBar]]); 88 | frame.scrollFrame.ScrollBarTop:SetSize(31, 256); 89 | frame.scrollFrame.ScrollBarTop:SetTexCoord(0, 0.484375, 0, 1); 90 | 91 | frame.scrollFrame.ScrollBarBottom = frame.scrollFrame:CreateTexture(nil, "BACKGROUND"); 92 | frame.scrollFrame.ScrollBarBottom:SetPoint("BOTTOMRIGHT", 6, -2); 93 | frame.scrollFrame.ScrollBarBottom:SetTexture ([[Interface\PaperDollInfoFrame\UI-Character-ScrollBar]]); 94 | frame.scrollFrame.ScrollBarBottom:SetSize(31, 106); 95 | frame.scrollFrame.ScrollBarBottom:SetTexCoord(0.515625, 1, 0, 0.4140625); 96 | 97 | frame.scrollFrame.ScrollBarMiddle = frame.scrollFrame:CreateTexture(nil, "BACKGROUND"); 98 | frame.scrollFrame.ScrollBarMiddle:SetPoint("BOTTOM", frame.scrollFrame.ScrollBarBottom, "TOP", 0, 0); 99 | frame.scrollFrame.ScrollBarMiddle:SetPoint("TOP", frame.scrollFrame.ScrollBarTop, "BOTTOM", 0, 0); 100 | frame.scrollFrame.ScrollBarMiddle:SetTexture ([[Interface\PaperDollInfoFrame\UI-Character-ScrollBar]]); 101 | frame.scrollFrame.ScrollBarMiddle:SetSize(31, 60); 102 | frame.scrollFrame.ScrollBarMiddle:SetTexCoord(0, 0.484375, 0.75, 1); 103 | 104 | frame.scrollFrame:SetClipsChildren(true); 105 | 106 | --- Make a basic content frame 107 | -- @param name The object name 108 | -- @param title The title to show 109 | local function MakeSubFrame(title) 110 | local sframe = CreateFrame("Frame", nil, frame.Inset); 111 | sframe:SetPoint("TOPLEFT", 0, 0); 112 | sframe:SetPoint("BOTTOMRIGHT", 0, 0); 113 | sframe:Hide(); 114 | sframe.title = sframe:CreateFontString(nil, "OVERLAY", "GameFontNormalMed2"); 115 | sframe.title:SetPoint("TOPLEFT", 20, -15); 116 | sframe.title:SetPoint("TOPRIGHT", -20, -15); 117 | sframe.title:SetText(title); 118 | return sframe; 119 | end 120 | 121 | --- Make an editbox 122 | -- @param parent The parent frame 123 | -- @param maxLen Maxmimum input length 124 | -- @param height (optional) 125 | -- @param isMultiline (optional) 126 | local function MakeEditBox(parent, maxLen, height, isMultiline) 127 | local edit = CreateFrame("EditBox", nil, parent, "BackdropTemplate"); 128 | edit:SetMaxLetters(maxLen); 129 | edit:SetAutoFocus(false); 130 | if height then 131 | edit:SetHeight(height); 132 | end 133 | edit:SetFont("Fonts\\FRIZQT__.TTF", 11); 134 | edit:SetJustifyH("LEFT"); 135 | edit:SetJustifyV("CENTER"); 136 | edit:SetTextInsets(7,7,7,7); 137 | edit:SetBackdrop({ 138 | bgFile = [[Interface\Buttons\WHITE8x8]], 139 | edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], 140 | edgeSize = 14, 141 | insets = {left = 3, right = 3, top = 3, bottom = 3}, 142 | }); 143 | edit:SetBackdropColor(0, 0, 0); 144 | edit:SetBackdropBorderColor(0.3, 0.3, 0.3); 145 | if isMultiline then 146 | edit:SetSpacing(3); 147 | edit:SetMultiLine(true); 148 | end 149 | edit:SetScript("OnEnterPressed", function(self) self:ClearFocus(); end); 150 | edit:SetScript("OnEscapePressed", function(self) self:ClearFocus(); end); 151 | edit:SetScript("OnEditFocusLost", function(self) EditBox_ClearHighlight(self); end); 152 | 153 | return edit; 154 | end 155 | 156 | -- Subframe with add form 157 | do 158 | local addFrame = MakeSubFrame(L["UI_ADDFORM_TITLE"]); 159 | addFrame.searchLabel = addFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal"); 160 | addFrame.searchLabel:SetPoint("TOPLEFT", addFrame.title, "BOTTOMLEFT", 0, -16); 161 | addFrame.searchLabel:SetPoint("TOPRIGHT", addFrame.title, "BOTTOMRIGHT", 0, -16); 162 | addFrame.searchLabel:SetText(L["UI_ADDFORM_NAME"]); 163 | addFrame.searchLabel:SetJustifyH("LEFT"); 164 | addFrame.searchEdit = MakeEditBox(addFrame, 40, 27, false); 165 | addFrame.searchEdit:SetPoint("TOPLEFT", addFrame.searchLabel, "BOTTOMLEFT", 0, -4); 166 | addFrame.searchEdit:SetPoint("TOPRIGHT", addFrame.searchLabel, "BOTTOMRIGHT", 0, -4); 167 | addFrame.okbutton = CreateFrame("Button", nil, addFrame, "OptionsButtonTemplate"); 168 | addFrame.okbutton:SetText(L["UI_ADDFORM_ADD_BUTTON"]); 169 | addFrame.okbutton:SetPoint("TOPLEFT", addFrame.searchEdit, "BOTTOMLEFT", 0, -10); 170 | addFrame.okbutton:SetWidth(125); 171 | addFrame.backbutton = CreateFrame("Button", nil, addFrame, "OptionsButtonTemplate"); 172 | addFrame.backbutton:SetText(L["UI_BACK"]); 173 | addFrame.backbutton:SetPoint("TOPRIGHT", addFrame.searchEdit, "BOTTOMRIGHT", 0, -10); 174 | addFrame.backbutton:SetWidth(75); 175 | frame.addFrame = addFrame; 176 | end 177 | 178 | -- Subframe with delete all form 179 | do 180 | local deleteAllFrame = MakeSubFrame(L["UI_RMALL_TITLE"]); 181 | deleteAllFrame.desc = deleteAllFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal"); 182 | deleteAllFrame.desc:SetPoint("TOPLEFT", deleteAllFrame.title, "BOTTOMLEFT", 0, -16); 183 | deleteAllFrame.desc:SetPoint("TOPRIGHT", deleteAllFrame.title, "BOTTOMRIGHT", 0, -16); 184 | deleteAllFrame.desc:SetText(L["UI_RMALL_DESC"]); 185 | deleteAllFrame.desc:SetJustifyH("LEFT"); 186 | deleteAllFrame.desc:SetJustifyV("CENTER"); 187 | deleteAllFrame.okbutton = CreateFrame("Button", nil, deleteAllFrame, "OptionsButtonTemplate"); 188 | deleteAllFrame.okbutton:SetText(L["UI_RMALL_REMOVE"]); 189 | deleteAllFrame.okbutton:SetPoint("TOPLEFT", deleteAllFrame.desc, "BOTTOMLEFT", 0, -10); 190 | deleteAllFrame.okbutton:SetWidth(125); 191 | deleteAllFrame.backbutton = CreateFrame("Button", nil, deleteAllFrame, "OptionsButtonTemplate"); 192 | deleteAllFrame.backbutton:SetText(L["UI_CANCEL"]); 193 | deleteAllFrame.backbutton:SetPoint("TOPRIGHT", deleteAllFrame.desc, "BOTTOMRIGHT", 0, -10); 194 | deleteAllFrame.backbutton:SetWidth(75); 195 | frame.deleteAllFrame = deleteAllFrame; 196 | end 197 | 198 | ---------------------------------------------------------------------------------------------------------------- 199 | -- List items for scroll frame 200 | ---------------------------------------------------------------------------------------------------------------- 201 | 202 | frame.scrollFrame.items = {}; 203 | 204 | --- Toggle the list item on/off 205 | local function ToggleItem(self) 206 | if _addon:ToggleEntry(self:GetParent().searchString:GetText()) then 207 | self:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\on]]); 208 | self:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\on]]); 209 | self:GetParent():SetBackdropColor(0.2,0.2,0.2,0.8); 210 | self:GetParent().searchString:SetTextColor(1, 1, 1, 1); 211 | else 212 | self:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\off]]); 213 | self:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\off]]); 214 | self:GetParent():SetBackdropColor(0.2,0.2,0.2,0.4); 215 | self:GetParent().searchString:SetTextColor(0.5, 0.5, 0.5, 1); 216 | end 217 | end 218 | 219 | --- Remove the list item 220 | local function RemoveItem(self) 221 | _addon:RemoveFromList(self:GetParent().searchString:GetText()); 222 | end 223 | 224 | for i = 1, MAX_ITEMS, 1 do 225 | local item = CreateFrame("Frame", nil, frame.scrollFrame, "BackdropTemplate"); 226 | 227 | item:SetHeight(LIST_ITEM_HEIGHT); 228 | item:SetPoint("TOPLEFT", 0, -LIST_ITEM_HEIGHT * (i-1)); 229 | item:SetPoint("TOPRIGHT", -23, -LIST_ITEM_HEIGHT * (i-1)); 230 | item:SetBackdrop({bgFile = [[Interface\AddOns\CChatNotifier\img\bar]]}); 231 | item:SetBackdropColor(0.2,0.2,0.2,0.8); 232 | 233 | item.searchString = item:CreateFontString(nil, "OVERLAY", "GameFontHighlight"); 234 | item.searchString:SetPoint("LEFT", 10, 0); 235 | item.searchString:SetPoint("RIGHT", -70, 0); 236 | item.searchString:SetHeight(10); 237 | item.searchString:SetJustifyH("LEFT"); 238 | 239 | item.delb = CreateFrame("Button", nil, item); 240 | item.delb:SetWidth(12); 241 | item.delb:SetHeight(12); 242 | item.delb:SetPoint("RIGHT", item, "RIGHT", -10, 0); 243 | item.delb:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\iclose]]); 244 | item.delb:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\iclose]]); 245 | item.delb:SetScript("OnClick", RemoveItem); 246 | 247 | item.disb = CreateFrame("Button", nil, item); 248 | item.disb:SetWidth(12); 249 | item.disb:SetHeight(12); 250 | item.disb:SetPoint("RIGHT", item.delb, "LEFT", -17, 0); 251 | item.disb:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\on]]); 252 | item.disb:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\on]]); 253 | item.disb:SetScript("OnClick", ToggleItem); 254 | 255 | frame.scrollFrame.items[i] = item; 256 | end 257 | 258 | 259 | ---------------------------------------------------------------------------------------------------------------- 260 | -- Frame functions 261 | ---------------------------------------------------------------------------------------------------------------- 262 | 263 | --- Switch displayed content 264 | -- @param name Which frame to show, "LIST", "ADD", "RM" , "RMALL", "RMOTHER", defaults to "LIST" 265 | function frame:ShowContent(name) 266 | if name == "ADD" then 267 | self.deleteAllFrame:Hide(); 268 | self.scrollFrame:Hide(); 269 | self.addFrame:Show(); 270 | return; 271 | end 272 | 273 | if name == "RM" then 274 | self.addFrame:Hide(); 275 | self.scrollFrame:Hide(); 276 | self.deleteAllFrame:Show(); 277 | return; 278 | end 279 | 280 | self.deleteAllFrame:Hide(); 281 | self.addFrame:Hide(); 282 | self.scrollFrame:Show(); 283 | end 284 | 285 | --- Update to current addon state 286 | function frame:UpdateAddonState() 287 | if CChatNotifier_settings.isActive then 288 | self.toggleBtn:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\on]]); 289 | self.toggleBtn:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\on]]); 290 | self.portrait:SetTexture([[Interface\AddOns\CChatNotifier\img\logo]]); 291 | self.TitleText:SetTextColor(1, 0.82, 0, 1); 292 | else 293 | self.toggleBtn:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\off]]); 294 | self.toggleBtn:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\off]]); 295 | self.portrait:SetTexture([[Interface\AddOns\CChatNotifier\img\logoo]]); 296 | self.TitleText:SetTextColor(1, 0, 0, 1); 297 | end 298 | end -------------------------------------------------------------------------------- /UI/MainUI_functions.lua: -------------------------------------------------------------------------------- 1 | local _addonName, _addon = ...; 2 | local L = _addon:GetLocalization(); 3 | 4 | local HEIGHT_NO_CONTENT = 71; 5 | local listItemHeight = CCNUI_MainUI.scrollFrame.items[1]:GetHeight(); 6 | local listElementCount = #CCNUI_MainUI.scrollFrame.items; 7 | local maxElementCount = listElementCount; 8 | 9 | local sortedEntries = {}; 10 | local entryCount = 0; 11 | 12 | ---------------------------------------------------------------------------------------------------------------- 13 | -- Top bar button actions 14 | ---------------------------------------------------------------------------------------------------------------- 15 | 16 | --- Open settings menu 17 | CCNUI_MainUI.settingsBtn:SetScript("OnClick", function(self) 18 | InterfaceOptionsFrame_OpenToCategory(_addonName); 19 | InterfaceOptionsFrame_OpenToCategory(_addonName); 20 | end); 21 | 22 | --- Open add frame 23 | CCNUI_MainUI.addBtn:SetScript("OnClick", function(self) 24 | _addon:MainUI_ShowAddForm(); 25 | end); 26 | 27 | --- Toggle addon on/off 28 | CCNUI_MainUI.toggleBtn:SetScript("OnClick", function(self) 29 | _addon:ToggleAddon(); 30 | CCNUI_MainUI:UpdateAddonState(); 31 | end); 32 | 33 | --- Open delete frame 34 | CCNUI_MainUI.deleteBtn:SetScript("OnClick", function(self) 35 | CCNUI_MainUI:ShowContent("RM"); 36 | end); 37 | 38 | 39 | ---------------------------------------------------------------------------------------------------------------- 40 | -- Content frame button actions 41 | ---------------------------------------------------------------------------------------------------------------- 42 | 43 | -- Delete all frame buttons 44 | CCNUI_MainUI.deleteAllFrame.okbutton:SetScript("OnClick", function(self) 45 | _addon:ClearList(); 46 | CCNUI_MainUI:ShowContent("LIST"); 47 | end); 48 | CCNUI_MainUI.deleteAllFrame.backbutton:SetScript("OnClick", function(self) 49 | CCNUI_MainUI:ShowContent("LIST"); 50 | end); 51 | 52 | -- Add frame buttons 53 | CCNUI_MainUI.addFrame.okbutton:SetScript("OnClick", function (self) 54 | local sstring = CCNUI_MainUI.addFrame.searchEdit:GetText(); 55 | sstring = strtrim(sstring); 56 | if string.len(sstring) == 0 then 57 | _addon:PrintError(L["UI_ADDFORM_ERR_NO_INPUT"]); 58 | return; 59 | end 60 | _addon:AddToList(sstring); 61 | CCNUI_MainUI:ShowContent("LIST"); 62 | end); 63 | CCNUI_MainUI.addFrame.backbutton:SetScript("OnClick", function (self) 64 | CCNUI_MainUI:ShowContent("LIST"); 65 | end); 66 | 67 | 68 | ---------------------------------------------------------------------------------------------------------------- 69 | -- Control functions 70 | ---------------------------------------------------------------------------------------------------------------- 71 | 72 | --- Show the add form 73 | -- @param search A search string to prefill (optional) 74 | function _addon:MainUI_ShowAddForm(search) 75 | if search == nil and CCNUI_MainUI:IsShown() and CCNUI_MainUI.addFrame:IsShown() then 76 | return; 77 | end 78 | 79 | CCNUI_MainUI.addFrame.searchEdit:SetText(""); 80 | if search ~= nil then 81 | CCNUI_MainUI.addFrame.searchEdit:SetText(search); 82 | CCNUI_MainUI.addFrame.searchEdit:SetCursorPosition(0); 83 | else 84 | CCNUI_MainUI.addFrame.searchEdit:SetFocus(); 85 | end 86 | 87 | CCNUI_MainUI:Show(); 88 | CCNUI_MainUI:ShowContent("ADD"); 89 | end 90 | 91 | --- Update scroll frame 92 | local function UpdateScrollFrame() 93 | local scrollHeight = 0; 94 | if entryCount > 0 then 95 | scrollHeight = (entryCount - listElementCount) * listItemHeight; 96 | if scrollHeight < 0 then 97 | scrollHeight = 0; 98 | end 99 | end 100 | 101 | local maxRange = (entryCount - listElementCount) * listItemHeight; 102 | if maxRange < 0 then 103 | maxRange = 0; 104 | end 105 | 106 | CCNUI_MainUI.scrollFrame.ScrollBar:SetMinMaxValues(0, maxRange); 107 | CCNUI_MainUI.scrollFrame.ScrollBar:SetValueStep(listItemHeight); 108 | CCNUI_MainUI.scrollFrame.ScrollBar:SetStepsPerPage(listElementCount-1); 109 | 110 | if CCNUI_MainUI.scrollFrame.ScrollBar:GetValue() == 0 then 111 | CCNUI_MainUI.scrollFrame.ScrollBar.ScrollUpButton:Disable(); 112 | else 113 | CCNUI_MainUI.scrollFrame.ScrollBar.ScrollUpButton:Enable(); 114 | end 115 | 116 | if (CCNUI_MainUI.scrollFrame.ScrollBar:GetValue() - scrollHeight) == 0 then 117 | CCNUI_MainUI.scrollFrame.ScrollBar.ScrollDownButton:Disable(); 118 | else 119 | CCNUI_MainUI.scrollFrame.ScrollBar.ScrollDownButton:Enable(); 120 | end 121 | 122 | for line = 1, listElementCount, 1 do 123 | local offsetLine = line + FauxScrollFrame_GetOffset(CCNUI_MainUI.scrollFrame); 124 | local item = CCNUI_MainUI.scrollFrame.items[line]; 125 | if offsetLine <= entryCount then 126 | curdta = CChatNotifier_data[sortedEntries[offsetLine]]; 127 | item.searchString:SetText(sortedEntries[offsetLine]); 128 | if curdta.active then 129 | item.disb:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\on]]); 130 | item.disb:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\on]]); 131 | item.disb:GetParent():SetBackdropColor(0.2,0.2,0.2,0.8); 132 | item.searchString:SetTextColor(1, 1, 1, 1); 133 | else 134 | item.disb:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\off]]); 135 | item.disb:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\off]]); 136 | item.disb:GetParent():SetBackdropColor(0.2,0.2,0.2,0.4); 137 | item.searchString:SetTextColor(0.5, 0.5, 0.5, 1); 138 | end 139 | item:Show(); 140 | else 141 | item:Hide(); 142 | end 143 | end 144 | end 145 | 146 | --- Recalculates height and shown item count 147 | -- @param ignoreHeight If true will not resize and reanchor UI 148 | local function RecalculateSize(ignoreHeight) 149 | local oldHeight = CCNUI_MainUI:GetHeight(); 150 | local showCount = math.floor((oldHeight - HEIGHT_NO_CONTENT + (listItemHeight/2 + 2)) / listItemHeight); 151 | 152 | if ignoreHeight ~= true then 153 | local newHeight = showCount * listItemHeight + HEIGHT_NO_CONTENT; 154 | 155 | CCNUI_MainUI:SetHeight(newHeight); 156 | 157 | local point, relTo, relPoint, x, y = CCNUI_MainUI:GetPoint(1); 158 | local yadjust = 0; 159 | 160 | if point == "CENTER" or point == "LEFT" or point == "RIGHT" then 161 | yadjust = (oldHeight - newHeight) / 2; 162 | elseif point == "BOTTOM" or point == "BOTTOMRIGHT" or point == "BOTTOMLEFT" then 163 | yadjust = oldHeight - newHeight; 164 | end 165 | 166 | CCNUI_MainUI:ClearAllPoints(); 167 | CCNUI_MainUI:SetPoint(point, relTo, relPoint, x, y + yadjust); 168 | end 169 | 170 | for i = 1, maxElementCount, 1 do 171 | if i > showCount then 172 | CCNUI_MainUI.scrollFrame.items[i]:Hide(); 173 | end 174 | end 175 | 176 | listElementCount = showCount; 177 | UpdateScrollFrame(); 178 | end 179 | 180 | --- Fill list from SV data 181 | function _addon:MainUI_UpdateList() 182 | entryCount = 0; 183 | wipe(sortedEntries); 184 | for k in pairs(CChatNotifier_data) do 185 | table.insert(sortedEntries, k); 186 | entryCount = entryCount + 1; 187 | end 188 | table.sort(sortedEntries); 189 | UpdateScrollFrame(); 190 | end 191 | 192 | --- Open the main list frame 193 | function _addon:MainUI_OpenList() 194 | CCNUI_MainUI:Show(); 195 | CCNUI_MainUI:ShowContent("LIST"); 196 | CCNUI_MainUI:UpdateAddonState(); 197 | RecalculateSize(true); 198 | UpdateScrollFrame(); 199 | end 200 | 201 | 202 | ---------------------------------------------------------------------------------------------------------------- 203 | -- Resize behaviour 204 | ---------------------------------------------------------------------------------------------------------------- 205 | 206 | -- Trigger update on scroll action 207 | CCNUI_MainUI.scrollFrame:SetScript("OnVerticalScroll", function(self, offset) 208 | FauxScrollFrame_OnVerticalScroll(self, offset, listItemHeight, UpdateScrollFrame); 209 | end); 210 | 211 | CCNUI_MainUI.resizeBtn:SetScript("OnMouseDown", function(self, button) 212 | CCNUI_MainUI:StartSizing("BOTTOMRIGHT"); 213 | end); 214 | 215 | -- Resize snaps to full list items shown, updates list accordingly 216 | CCNUI_MainUI.resizeBtn:SetScript("OnMouseUp", function(self, button) 217 | CCNUI_MainUI:StopMovingOrSizing(); 218 | RecalculateSize(); 219 | end); -------------------------------------------------------------------------------- /UI/listFrame.lua: -------------------------------------------------------------------------------- 1 | local _addonName, _addon = ...; 2 | local L = _addon:GetLocalization(); 3 | local LISTITEMHEIGHT = 27; 4 | 5 | -------------------------------- 6 | -- Setup UI elements 7 | -------------------------------- 8 | local listElements = {}; 9 | local listElemCount = 0; 10 | 11 | -- Main frame 12 | local listFrame = CreateFrame("Frame", "CChatNotifierListUI", UIParent, "ButtonFrameTemplate"); 13 | listFrame:SetPoint("CENTER", 0, 0); 14 | listFrame:SetWidth(275); 15 | listFrame:SetHeight(340); 16 | listFrame:SetResizable(true); 17 | listFrame:SetClampedToScreen(true); 18 | listFrame:SetMaxResize(400, 449); 19 | listFrame:SetMinResize(250, 340); 20 | listFrame:SetMovable(true); 21 | listFrame:EnableMouse(true); 22 | listFrame:RegisterForDrag("LeftButton"); 23 | listFrame:SetScript("OnDragStart", listFrame.StartMoving); 24 | listFrame:SetScript("OnDragStop", listFrame.StopMovingOrSizing); 25 | listFrame.TitleText:SetText(_addonName); 26 | listFrame.portrait:SetTexture([[Interface\AddOns\CChatNotifier\img\logo]]); 27 | listFrame:Hide(); 28 | 29 | -- Delete button for delete all function 30 | local deleteButton = CreateFrame("Button", nil, listFrame); 31 | deleteButton:SetSize(18, 18); 32 | deleteButton:SetPoint("TOPRIGHT", -15, -35); 33 | deleteButton:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\trash]]); 34 | deleteButton:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\trash]]); 35 | 36 | -- Add button for switching to add content 37 | local addButton = CreateFrame("Button", nil, listFrame); 38 | addButton:SetSize(15, 15); 39 | addButton:SetPoint("RIGHT", deleteButton, "LEFT", -15, 0); 40 | addButton:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\iplus]]); 41 | addButton:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\iplus]]); 42 | 43 | -- Add button for toggling addon on/off 44 | local toggleButton = CreateFrame("Button", nil, listFrame); 45 | toggleButton:SetSize(15, 15); 46 | toggleButton:SetPoint("RIGHT", addButton, "LEFT", -15, 0); 47 | toggleButton:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\on]]); 48 | toggleButton:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\on]]); 49 | 50 | -- Settings button 51 | local settingsButton = CreateFrame("Button", nil, listFrame); 52 | settingsButton:SetSize(18, 18); 53 | settingsButton:SetPoint("TOPLEFT", 70, -35); 54 | settingsButton:SetNormalTexture([[interface/scenarios/scenarioicon-interact.blp]]); 55 | settingsButton:SetHighlightTexture([[interface/scenarios/scenarioicon-interact.blp]]); 56 | 57 | -- Resize knob 58 | local resizeButton = CreateFrame("Button", nil, listFrame); 59 | resizeButton:SetSize(18, 18); 60 | resizeButton:SetPoint("BOTTOMRIGHT", -3, 3); 61 | resizeButton:SetNormalTexture([[Interface\ChatFrame\UI-ChatIM-SizeGrabber-Up]]); 62 | resizeButton:SetHighlightTexture([[Interface\ChatFrame\UI-ChatIM-SizeGrabber-Highlight]]); 63 | resizeButton:SetPushedTexture([[Interface\ChatFrame\UI-ChatIM-SizeGrabber-Down]]); 64 | 65 | -- Subframe with scroll list of targets 66 | local scrollFrame = CreateFrame("ScrollFrame", "CChatNotifierListUIScroll", listFrame.Inset, "UIPanelScrollFrameTemplate2"); 67 | local scrollChild = CreateFrame("Frame", nil, scrollFrame); 68 | scrollFrame:SetPoint("TOPLEFT", 3, -3); 69 | scrollFrame:SetPoint("BOTTOMRIGHT", -5, 3); 70 | scrollFrame:SetClipsChildren(true); 71 | scrollFrame.ScrollBar:ClearAllPoints(); 72 | scrollFrame.ScrollBar:SetPoint("TOPRIGHT", scrollFrame, "TOPRIGHT", 0, -17); 73 | scrollFrame.ScrollBar:SetPoint("BOTTOMRIGHT", scrollFrame, "BOTTOMRIGHT", 0, 17); 74 | scrollChild:SetSize(scrollFrame:GetWidth()-24, 100); 75 | scrollFrame:SetScrollChild(scrollChild); 76 | 77 | --- Make a basic content frame 78 | -- @param name The object name 79 | -- @param title The title to show 80 | local function MakeSubFrame(name, title) 81 | local sframe = CreateFrame("Frame", name, listFrame.Inset); 82 | sframe:SetPoint("TOPLEFT", 0, 0); 83 | sframe:SetPoint("BOTTOMRIGHT", 0, 0); 84 | sframe:Hide(); 85 | sframe.title = sframe:CreateFontString(nil, "OVERLAY", "GameFontNormalMed2"); 86 | sframe.title:SetPoint("TOPLEFT", 20, -15); 87 | sframe.title:SetPoint("TOPRIGHT", -20, -15); 88 | sframe.title:SetText(title); 89 | return sframe; 90 | end 91 | 92 | --- Make an editbox 93 | -- @param parent The parent frame 94 | -- @param maxLen Maxmimum input length 95 | -- @param height (optional) 96 | -- @param isMultiline (optional) 97 | local function MakeEditBox(parent, maxLen, height, isMultiline) 98 | local edit = CreateFrame("EditBox", nil, parent, "BackdropTemplate"); 99 | edit:SetMaxLetters(maxLen); 100 | edit:SetAutoFocus(false); 101 | if height then 102 | edit:SetHeight(height); 103 | end 104 | edit:SetFont("Fonts\\FRIZQT__.TTF", 11); 105 | edit:SetJustifyH("LEFT"); 106 | edit:SetJustifyV("CENTER"); 107 | edit:SetTextInsets(7,7,7,7); 108 | edit:SetBackdrop({ 109 | bgFile = [[Interface\Buttons\WHITE8x8]], 110 | edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], 111 | edgeSize = 14, 112 | insets = {left = 3, right = 3, top = 3, bottom = 3}, 113 | }); 114 | edit:SetBackdropColor(0, 0, 0); 115 | edit:SetBackdropBorderColor(0.3, 0.3, 0.3); 116 | if isMultiline then 117 | edit:SetSpacing(3); 118 | edit:SetMultiLine(true); 119 | end 120 | edit:SetScript("OnEnterPressed", function(self) self:ClearFocus(); end); 121 | edit:SetScript("OnEscapePressed", function(self) self:ClearFocus(); end); 122 | edit:SetScript("OnEditFocusLost", function(self) EditBox_ClearHighlight(self); end); 123 | 124 | return edit; 125 | end 126 | 127 | -- Subframe with add form 128 | local addFrame = MakeSubFrame(nil, L["UI_ADDFORM_TITLE"]); 129 | addFrame.searchLabel = addFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal"); 130 | addFrame.searchLabel:SetPoint("TOPLEFT", addFrame.title, "BOTTOMLEFT", 0, -16); 131 | addFrame.searchLabel:SetPoint("TOPRIGHT", addFrame.title, "BOTTOMRIGHT", 0, -16); 132 | addFrame.searchLabel:SetText(L["UI_ADDFORM_NAME"]); 133 | addFrame.searchLabel:SetJustifyH("LEFT"); 134 | addFrame.searchEdit = MakeEditBox(addFrame, 40, 27, false); 135 | addFrame.searchEdit:SetPoint("TOPLEFT", addFrame.searchLabel, "BOTTOMLEFT", 0, -4); 136 | addFrame.searchEdit:SetPoint("TOPRIGHT", addFrame.searchLabel, "BOTTOMRIGHT", 0, -4); 137 | addFrame.okbutton = CreateFrame("Button", nil, addFrame, "OptionsButtonTemplate"); 138 | addFrame.okbutton:SetText(L["UI_ADDFORM_ADD_BUTTON"]); 139 | addFrame.okbutton:SetPoint("TOPLEFT", addFrame.searchEdit, "BOTTOMLEFT", 0, -10); 140 | addFrame.okbutton:SetWidth(125); 141 | addFrame.backbutton = CreateFrame("Button", nil, addFrame, "OptionsButtonTemplate"); 142 | addFrame.backbutton:SetText(L["UI_BACK"]); 143 | addFrame.backbutton:SetPoint("TOPRIGHT", addFrame.searchEdit, "BOTTOMRIGHT", 0, -10); 144 | addFrame.backbutton:SetWidth(75); 145 | 146 | -- Subframe with delete all form 147 | local deleteAllFrame = MakeSubFrame(nil, L["UI_RMALL_TITLE"]); 148 | deleteAllFrame.desc = deleteAllFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal"); 149 | deleteAllFrame.desc:SetPoint("TOPLEFT", deleteAllFrame.title, "BOTTOMLEFT", 0, -16); 150 | deleteAllFrame.desc:SetPoint("TOPRIGHT", deleteAllFrame.title, "BOTTOMRIGHT", 0, -16); 151 | deleteAllFrame.desc:SetText(L["UI_RMALL_DESC"]); 152 | deleteAllFrame.desc:SetJustifyH("LEFT"); 153 | deleteAllFrame.desc:SetJustifyV("CENTER"); 154 | deleteAllFrame.okbutton = CreateFrame("Button", nil, deleteAllFrame, "OptionsButtonTemplate"); 155 | deleteAllFrame.okbutton:SetText(L["UI_RMALL_REMOVE"]); 156 | deleteAllFrame.okbutton:SetPoint("TOPLEFT", deleteAllFrame.desc, "BOTTOMLEFT", 0, -10); 157 | deleteAllFrame.okbutton:SetWidth(125); 158 | deleteAllFrame.backbutton = CreateFrame("Button", nil, deleteAllFrame, "OptionsButtonTemplate"); 159 | deleteAllFrame.backbutton:SetText(L["UI_CANCEL"]); 160 | deleteAllFrame.backbutton:SetPoint("TOPRIGHT", deleteAllFrame.desc, "BOTTOMRIGHT", 0, -10); 161 | deleteAllFrame.backbutton:SetWidth(75); 162 | 163 | 164 | -------------------------------- 165 | -- UI functions 166 | -------------------------------- 167 | 168 | -- Resize scrollchild while resizing, has no anchors 169 | resizeButton:SetScript("OnMouseDown", function(self, button) 170 | listFrame:StartSizing("BOTTOMRIGHT"); 171 | resizeButton:SetScript("OnUpdate", function() 172 | scrollChild:SetWidth(scrollFrame:GetWidth()-24); 173 | end); 174 | end); 175 | resizeButton:SetScript("OnMouseUp", function(self, button) 176 | listFrame:StopMovingOrSizing(); 177 | resizeButton:SetScript("OnUpdate", nil); 178 | scrollChild:SetWidth(scrollFrame:GetWidth()-24); 179 | end); 180 | 181 | --- Switch displayed content 182 | -- @param frame Which frame to show, "LIST", "ADD", "RM", defaults to "LIST" 183 | local function ShowSubFrame(frame) 184 | if frame == "ADD" then 185 | addFrame:Show(); 186 | scrollFrame:Hide(); 187 | deleteAllFrame:Hide(); 188 | return; 189 | end 190 | 191 | if frame == "RM" then 192 | addFrame:Hide(); 193 | scrollFrame:Hide(); 194 | deleteAllFrame:Show(); 195 | return; 196 | end 197 | 198 | scrollFrame:Show(); 199 | addFrame:Hide(); 200 | deleteAllFrame:Hide(); 201 | end 202 | 203 | --- Update to current addon state 204 | local function ToggleUpdate() 205 | if CChatNotifier_settings.isActive then 206 | toggleButton:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\on]]); 207 | toggleButton:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\on]]); 208 | listFrame.portrait:SetTexture([[Interface\AddOns\CChatNotifier\img\logo]]); 209 | listFrame.TitleText:SetTextColor(1, 0.82, 0, 1); 210 | else 211 | toggleButton:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\off]]); 212 | toggleButton:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\off]]); 213 | listFrame.portrait:SetTexture([[Interface\AddOns\CChatNotifier\img\logoo]]); 214 | listFrame.TitleText:SetTextColor(1, 0, 0, 1); 215 | end 216 | end 217 | 218 | --- Open settings menu 219 | settingsButton:SetScript("OnClick", function(self) 220 | InterfaceOptionsFrame_OpenToCategory(_addonName); 221 | InterfaceOptionsFrame_OpenToCategory(_addonName); 222 | end); 223 | 224 | --- Open add subframe when plus is clicked 225 | addButton:SetScript("OnClick", function(self) 226 | if addFrame:IsShown() then 227 | return; 228 | end 229 | _addon:ShowAddForm(); 230 | end); 231 | 232 | --- Toggle addon on/off 233 | toggleButton:SetScript("OnClick", function(self) 234 | _addon:ToggleAddon(); 235 | ToggleUpdate(); 236 | end); 237 | 238 | --- Show dropdown when delete context button is clicked 239 | deleteButton:SetScript("OnClick", function(self) 240 | ShowSubFrame("RM"); 241 | end); 242 | 243 | -- Delete all frame buttons 244 | deleteAllFrame.okbutton:SetScript("OnClick", function(self) 245 | _addon:ClearList(); 246 | ShowSubFrame("LIST"); 247 | end); 248 | deleteAllFrame.backbutton:SetScript("OnClick", function(self) 249 | ShowSubFrame("LIST"); 250 | end); 251 | 252 | -- Add frame buttons 253 | addFrame.okbutton:SetScript ("OnClick", function (self) 254 | local sstring = addFrame.searchEdit:GetText(); 255 | sstring = strtrim(sstring); 256 | if string.len(sstring) == 0 then 257 | _addon:PrintError(L["UI_ADDFORM_ERR_NO_INPUT"]); 258 | return; 259 | end 260 | _addon:AddToList(sstring); 261 | ShowSubFrame("LIST"); 262 | end); 263 | addFrame.backbutton:SetScript ("OnClick", function (self) 264 | ShowSubFrame("LIST"); 265 | end); 266 | 267 | --- Create a list element 268 | -- @param pos The position to create it for 269 | local function CreateListElement(pos) 270 | if listElements[pos] ~= nil then 271 | return; 272 | end 273 | 274 | local item = CreateFrame("Frame", nil, scrollFrame, "BackdropTemplate"); 275 | item:SetHeight(LISTITEMHEIGHT); 276 | 277 | if pos == 1 then 278 | item:SetPoint("TOPLEFT", scrollChild, "TOPLEFT", 0, 0); 279 | item:SetPoint("TOPRIGHT", scrollChild, "TOPRIGHT", 0, 0); 280 | else 281 | item:SetPoint("TOPLEFT", listElements[pos-1], "BOTTOMLEFT", 0, 0); 282 | item:SetPoint("TOPRIGHT", listElements[pos-1], "BOTTOMRIGHT", 0, 0); 283 | end 284 | 285 | item:SetBackdrop({bgFile = [[Interface\AddOns\CChatNotifier\img\bar]]}); 286 | item:SetBackdropColor(0.2,0.2,0.2,0.8); 287 | 288 | item.searchString = item:CreateFontString(nil, "OVERLAY", "GameFontHighlight"); 289 | item.searchString:SetPoint("LEFT", 10, 0); 290 | item.searchString:SetPoint("RIGHT", -70, 0); 291 | item.searchString:SetHeight(10); 292 | item.searchString:SetJustifyH("LEFT"); 293 | 294 | item.delb = CreateFrame("Button", nil, item); 295 | item.delb:SetWidth(12); 296 | item.delb:SetHeight(12); 297 | item.delb:SetPoint("RIGHT", item, "RIGHT", -10, 0); 298 | item.delb:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\iclose]]); 299 | item.delb:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\iclose]]); 300 | 301 | item.delb:SetScript("OnClick", function(self) 302 | _addon:RemoveFromList(self:GetParent().searchString:GetText()); 303 | end) 304 | 305 | item.disb = CreateFrame("Button", nil, item, "BackdropTemplate"); 306 | item.disb:SetWidth(12); 307 | item.disb:SetHeight(12); 308 | item.disb:SetPoint("RIGHT", item.delb, "LEFT", -17, 0); 309 | item.disb:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\on]]); 310 | item.disb:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\on]]); 311 | 312 | item.disb:SetScript("OnClick", function(self) 313 | local isOn = _addon:ToggleEntry(self:GetParent().searchString:GetText()); 314 | if isOn then 315 | self:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\on]]); 316 | self:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\on]]); 317 | self:GetParent():SetBackdropColor(0.2,0.2,0.2,0.8); 318 | self:GetParent().searchString:SetTextColor(1, 1, 1, 1); 319 | else 320 | self:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\off]]); 321 | self:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\off]]); 322 | self:GetParent():SetBackdropColor(0.2,0.2,0.2,0.4); 323 | self:GetParent().searchString:SetTextColor(0.5, 0.5, 0.5, 1); 324 | end 325 | end) 326 | 327 | listElemCount = pos; 328 | listElements[pos] = item; 329 | end 330 | 331 | 332 | -------------------------------- 333 | -- Addon functions 334 | -------------------------------- 335 | 336 | --- Fill list from SV data 337 | function _addon:FillList() 338 | local count = 0; 339 | local tkeys = {}; 340 | for k in pairs(CChatNotifier_data) do 341 | table.insert(tkeys, k); 342 | count = count + 1; 343 | end 344 | table.sort(tkeys); 345 | 346 | local curitm, curdta; 347 | for i, search in ipairs(tkeys) do 348 | CreateListElement(i); 349 | curitm = listElements[i]; 350 | curdta = CChatNotifier_data[search]; 351 | curitm.searchString:SetText(search); 352 | 353 | if curdta.active then 354 | curitm.disb:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\on]]); 355 | curitm.disb:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\on]]); 356 | curitm.disb:GetParent():SetBackdropColor(0.2,0.2,0.2,0.8); 357 | curitm.searchString:SetTextColor(1, 1, 1, 1); 358 | else 359 | curitm.disb:SetNormalTexture([[Interface\AddOns\CChatNotifier\img\off]]); 360 | curitm.disb:SetHighlightTexture([[Interface\AddOns\CChatNotifier\img\off]]); 361 | curitm.disb:GetParent():SetBackdropColor(0.2,0.2,0.2,0.4); 362 | curitm.searchString:SetTextColor(0.5, 0.5, 0.5, 1); 363 | end 364 | 365 | curitm:Show(); 366 | end 367 | 368 | for i = count + 1, listElemCount, 1 do 369 | listElements[i]:Hide(); 370 | end 371 | 372 | scrollChild:SetHeight(count*LISTITEMHEIGHT); 373 | end 374 | 375 | --- Show the add form 376 | -- @param search A search string to prefill (optional) 377 | function _addon:ShowAddForm(search) 378 | if search == nil and listFrame:IsShown() and addFrame:IsShown() then 379 | return; 380 | end 381 | 382 | addFrame.searchEdit:SetText(""); 383 | if search ~= nil then 384 | addFrame.searchEdit:SetText(search); 385 | addFrame.searchEdit:SetCursorPosition(0); 386 | else 387 | addFrame.searchEdit:SetFocus(); 388 | end 389 | 390 | listFrame:Show(); 391 | ShowSubFrame("ADD"); 392 | end 393 | 394 | --- Open the main list frame 395 | function _addon:OpenList() 396 | listFrame:Show(); 397 | ShowSubFrame("LIST"); 398 | scrollChild:SetWidth(scrollFrame:GetWidth()-24); 399 | ToggleUpdate(); 400 | end -------------------------------------------------------------------------------- /UI/minimapButton.lua: -------------------------------------------------------------------------------- 1 | local _addonName, _addon = ...; 2 | local L = _addon:GetLocalization(); 3 | 4 | -------------------------------- 5 | -- Setup UI elements 6 | -------------------------------- 7 | local mmicon = CreateFrame("Button", "CChatNotifierMMIcon", Minimap); 8 | 9 | mmicon:SetClampedToScreen(true); 10 | mmicon:SetMovable(true); 11 | mmicon:EnableMouse(true); 12 | mmicon:RegisterForDrag("LeftButton"); 13 | mmicon:RegisterForClicks("LeftButtonUp", "RightButtonUp"); 14 | mmicon:SetFrameStrata("LOW"); 15 | mmicon:SetWidth(31); 16 | mmicon:SetHeight(31); 17 | mmicon:SetFrameLevel(9); 18 | mmicon:SetHighlightTexture([[Interface\Minimap\UI-Minimap-ZoomButton-Highlight]]); 19 | mmicon:SetPoint("BOTTOMLEFT", Minimap, "BOTTOMLEFT", 0, 0); 20 | mmicon.overlay = mmicon:CreateTexture(nil, 'OVERLAY'); 21 | mmicon.overlay:SetWidth(53); 22 | mmicon.overlay:SetHeight(53); 23 | mmicon.overlay:SetTexture([[Interface\Minimap\MiniMap-TrackingBorder]]); 24 | mmicon.overlay:SetPoint("TOPLEFT", 0,0); 25 | mmicon.icon = mmicon:CreateTexture(nil, "BACKGROUND"); 26 | mmicon.icon:SetWidth(20); 27 | mmicon.icon:SetHeight(20); 28 | mmicon.icon:SetTexture([[Interface\AddOns\CChatNotifier\img\logo]]); 29 | mmicon.icon:SetTexCoord(0.05, 0.95, 0.05, 0.95); 30 | mmicon.icon:SetPoint("CENTER",0,1); 31 | 32 | 33 | -------------------------------- 34 | -- UI functions 35 | -------------------------------- 36 | 37 | -- Open on click 38 | mmicon:SetScript("OnClick", function(self, arg1) 39 | _addon:MainUI_OpenList(); 40 | end) 41 | 42 | -- Tooltip 43 | mmicon:SetScript("OnEnter", function(self, arg1) 44 | GameTooltip:SetOwner(self, "ANCHOR_LEFT", 3, -10); 45 | GameTooltip:SetText(L["UI_MMB_OPEN"]); 46 | GameTooltip:Show(); 47 | end) 48 | mmicon:SetScript("OnLeave", function(self, arg1) 49 | GameTooltip:Hide(); 50 | end) 51 | 52 | --- Snap icon to minimap 53 | -- @param refX The x coordinate of the reference point 54 | -- @param refY The y coordinate of the reference point 55 | local function SnapPosition(refX, refY) 56 | local distTarget = (Minimap:GetWidth()/2 + mmicon:GetWidth()/2 - 5); 57 | local mmX, mmY = Minimap:GetCenter(); 58 | local angle = math.atan2( refY-mmY, refX-mmX ); 59 | mmicon:ClearAllPoints(); 60 | mmicon:SetPoint("CENTER", Minimap, "CENTER", (math.cos(angle) * distTarget), (math.sin(angle) * distTarget)); 61 | end 62 | 63 | local function OnUpdateHandler() 64 | local uiScale, cx, cy = UIParent:GetEffectiveScale(), GetCursorPosition(); 65 | SnapPosition(cx/uiScale, cy/uiScale); 66 | end 67 | 68 | mmicon:SetScript("OnDragStart", function(self) 69 | if CChatNotifier_settings.snapToMinimap then 70 | self:SetScript("OnUpdate", OnUpdateHandler); 71 | end 72 | self:StartMoving(); 73 | end) 74 | 75 | mmicon:SetScript("OnDragStop", function(self) 76 | self:SetScript("OnUpdate", nil); 77 | self:StopMovingOrSizing(); 78 | end) 79 | 80 | 81 | -------------------------------- 82 | -- Addon functions 83 | -------------------------------- 84 | 85 | --- Snap minimap button to minimap from current position 86 | function _addon:MinimapButtonSnap() 87 | local x, y = mmicon:GetCenter(); 88 | SnapPosition(x, y); 89 | end 90 | 91 | --- Update texture to reflect state 92 | function _addon:MinimapButtonUpdate() 93 | if CChatNotifier_settings.isActive then 94 | mmicon.icon:SetTexture([[Interface\AddOns\CChatNotifier\img\logo]]); 95 | else 96 | mmicon.icon:SetTexture([[Interface\AddOns\CChatNotifier\img\logoo]]); 97 | end 98 | if CChatNotifier_settings.showMinimapButton then 99 | mmicon:Show(); 100 | else 101 | mmicon:Hide(); 102 | end 103 | end -------------------------------------------------------------------------------- /i18n/deDE.lua: -------------------------------------------------------------------------------- 1 | local _addonName, _addon = ...; 2 | local L = _addon:AddLocalization("deDE", true); 3 | if L == nil then return; end 4 | 5 | L["FIRST_START_MSG"] = "|cFF00FF00" .. _addonName .. "|r|cFFffb178: Listen-UI kann mit /ccn oder dem Button an der Minimap geöffnet werden. Den Button kannst du in den Einstellungen verstecken."; 6 | 7 | L["CHAT_NOTIFY_FOUND_SAYYELL"] = "Begriff |cFF00FF00%s|r gefunden! |cFFFF66FF|Hplayer:%s|h[%s]|h|r: %s"; 8 | L["CHAT_NOTIFY_FOUND_CHANNEL"] = "Begriff |cFF00FF00%s|r gefunden! |cFFFF66FF|Hplayer:%s|h[%s]|h|r in %s: %s"; 9 | 10 | L["CHAT_NOTIFY_FORMAT"] = "<>[{T}] <00ff00>{K}<> gefunden! [{S}][{P}]<>: {MS}<00ff00>{MF}{ME}"; 11 | L["ERR_NOTIFY_FORMAT_MISSING"] = "Kein Format festgelegt, gehe in die Einstellungen um eines zu erstellen, oder auf den Standardwert zurückzusetzen."; 12 | 13 | L["SOUND_NO_SOUND"] = "- Kein Ton -"; 14 | 15 | L["SETTINGS_HEAD_GENERAL"] = "Allgemein"; 16 | L["SETTINGS_PLAY_SOUND"] = "Ton aktivieren"; 17 | L["SETTINGS_PLAY_SOUND_TT"] = "Spiele Ton wenn ein Schlüsselwort gefunden wurde."; 18 | L["SETTINGS_TEST_CHAT"] = "Benachrichtigung testen"; 19 | L["SETTINGS_CHATFRAME"] = "Chatfenster:"; 20 | L["SETTINGS_CHATFRAME_TT"] = "Wähle in welchem Chatfenster (Tab) die Benachrichtigung erscheinen soll."; 21 | L["SETTINGS_MINIMAP"] = "Minimapbutton anzeigen"; 22 | L["SETTINGS_MINIMAP_TT"] = "Zeige Button zum Öffnen der Liste an. Alternativ kann /ccn verwendet werden."; 23 | L["SETTINGS_SNAP_MINIMAP"] = "Button an Minimap einrasten"; 24 | L["SETTINGS_SNAP_MINIMAP_TT"] = "Raste den Minimapbutton an Rand der Minimap ein."; 25 | L["SETTINGS_SOUNDID"] = "Benachrichtigungston:"; 26 | L["SETTINGS_SOUNDID_TT"] = "Wähle welcher Ton als Benachrichtigung abgespielt werden soll."; 27 | L["SETTINGS_HEAD_FORMAT"] = "Benachrichtigungsformat"; 28 | L["SETTINGS_FORMAT_DESC"] = 29 | [[Du kannst ein eigenes Format für Benachrichtigungen erstellen! Siehe Standardformat bezüglich Nutzung. 30 | 31 | |cFFFFFF00Setze Farben mit: 32 | |cFF00FFFF|r Färbt nachfolgenden Text. RRGGBB ist eine Hexfarbe, nutze google wenn nötig! 33 | |cFF00FFFF<>|r Legt die Standardfarbe fest, weiß wenn nicht gesetzt. 34 | |cFF00FFFF<>|r Nachfolgender Text hat wieder Standardfarbe. 35 | 36 | |cFFFFFF00Platzhalter für Inhalt: 37 | |cFF00FFFF{K}|r Das gefunde Schlüsselwort. 38 | |cFF00FFFF{S}|r Der Quellenkanal der Nachricht. 39 | |cFF00FFFF{P}|r Spielerlink der Verfassers. 40 | |cFF00FFFF{MS}|r Anfang der Nachricht. 41 | |cFF00FFFF{MF}|r Nachrichtenteil mit gefundenem Schlüsselwort. 42 | |cFF00FFFF{ME}|r Der Rest der Nachricht. 43 | |cFF00FFFF{T}|r Die aktuelle Serverzeit als hh:mm.]]; 44 | L["SETTINGS_FORMAT_RESET"] = "Format zurücksetzen"; 45 | 46 | L["VICINITY"] = "Umgebung"; 47 | 48 | L["UI_ADDFORM_TITLE"] = "Neue Suche"; 49 | L["UI_ADDFORM_NAME"] = "Gebe Suchbegriff(e) ein. Mehrere Wörter durch ein Komma trennen, nutze einen Punkt als Platzhalter:"; 50 | L["UI_ADDFORM_ADD_BUTTON"] = "Hinzufügen"; 51 | L["UI_BACK"] = "Zurück"; 52 | L["UI_ADDFORM_ERR_NO_INPUT"] = "Begriffsfeld ist leer!"; 53 | 54 | L["UI_RMALL_TITLE"] = "Alles Löschen"; 55 | L["UI_RMALL_DESC"] = "Alle Einträge aus der Liste löschen?"; 56 | L["UI_RMALL_REMOVE"] = "Löschen"; 57 | L["UI_CANCEL"] = "Abbrechen"; 58 | 59 | L["UI_MMB_OPEN"] = "Öffne " .. _addonName; -------------------------------------------------------------------------------- /i18n/enUS.lua: -------------------------------------------------------------------------------- 1 | local _addonName, _addon = ...; 2 | local L = _addon:AddLocalization("enUS", true); 3 | if L == nil then return; end 4 | 5 | L["FIRST_START_MSG"] = "|cFF00FF00" .. _addonName .. "|r|cFFffb178: List UI can be opened with /ccn or the button on the minimap. You can hide the button in settings."; 6 | 7 | L["CHAT_NOTIFY_FOUND_SAYYELL"] = "Found |cFF00FF00%s|r! |cFFFF66FF|Hplayer:%s|h[%s]|h|r: %s"; 8 | L["CHAT_NOTIFY_FOUND_CHANNEL"] = "Found |cFF00FF00%s|r! |cFFFF66FF|Hplayer:%s|h[%s]|h|r in %s: %s"; 9 | 10 | L["CHAT_NOTIFY_FORMAT"] = "<>[{T}] Found <00ff00>{K}<>! [{S}][{P}]<>: {MS}<00ff00>{MF}{ME}"; 11 | L["ERR_NOTIFY_FORMAT_MISSING"] = "No format set, go into settings and create a format or reset it to default."; 12 | 13 | L["SOUND_NO_SOUND"] = "- No sound -"; 14 | 15 | L["SETTINGS_HEAD_GENERAL"] = "General"; 16 | L["SETTINGS_PLAY_SOUND"] = "Activate sound"; 17 | L["SETTINGS_PLAY_SOUND_TT"] = "Play sound when a search keyword was found."; 18 | L["SETTINGS_TEST_CHAT"] = "Test notification"; 19 | L["SETTINGS_CHATFRAME"] = "Notification chatframe:"; 20 | L["SETTINGS_CHATFRAME_TT"] = "Choose chatframe (tab) in which the notifications should appear."; 21 | L["SETTINGS_SNAP_MINIMAP"] = "Snap button to minimap"; 22 | L["SETTINGS_SNAP_MINIMAP_TT"] = "Snap minimap button to minimap border."; 23 | L["SETTINGS_MINIMAP"] = "Show minimap button"; 24 | L["SETTINGS_MINIMAP_TT"] = "Show button for opening the list. Alternatively you can use /ccn."; 25 | L["SETTINGS_SOUNDID"] = "Notification sound:"; 26 | L["SETTINGS_SOUNDID_TT"] = "Choose sound to play as notification."; 27 | L["SETTINGS_HEAD_FORMAT"] = "Notification Format"; 28 | L["SETTINGS_FORMAT_DESC"] = 29 | [[You can set a custom format for the notification message! See default format for how to use it. 30 | 31 | |cFFFFFF00Set colors using: 32 | |cFF00FFFF|r Color subsequent text. RRGGBB is a hexcolor, use google if needed! 33 | |cFF00FFFF<>|r Define default color, white if not set. 34 | |cFF00FFFF<>|r Subsequent text will have the default color. 35 | 36 | |cFFFFFF00Placeholders for content: 37 | |cFF00FFFF{K}|r The found keyword you set. 38 | |cFF00FFFF{S}|r The source channel of the message. 39 | |cFF00FFFF{P}|r Playerlink for author of the message. 40 | |cFF00FFFF{MS}|r Start of the message. 41 | |cFF00FFFF{MF}|r The part with the found keyword. 42 | |cFF00FFFF{ME}|r The rest of the message. 43 | |cFF00FFFF{T}|r The current server time as hh:mm.]]; 44 | L["SETTINGS_FORMAT_RESET"] = "Reset format to default"; 45 | 46 | L["VICINITY"] = "vicinity"; 47 | 48 | L["UI_ADDFORM_TITLE"] = "New Search"; 49 | L["UI_ADDFORM_NAME"] = "Enter keyword(s) below. Multiple words are separated by a comma, use dot for wildcards:"; 50 | L["UI_ADDFORM_ADD_BUTTON"] = "Add"; 51 | L["UI_BACK"] = "Back"; 52 | L["UI_ADDFORM_ERR_NO_INPUT"] = "Term field is empty!"; 53 | 54 | L["UI_RMALL_TITLE"] = "Delete Everything"; 55 | L["UI_RMALL_DESC"] = "Delete all entries from the list?"; 56 | L["UI_RMALL_REMOVE"] = "Delete"; 57 | L["UI_CANCEL"] = "Cancel"; 58 | 59 | L["UI_MMB_OPEN"] = "Open " .. _addonName; -------------------------------------------------------------------------------- /i18n/loc.lua: -------------------------------------------------------------------------------- 1 | local _addonName, _addon = ...; 2 | local clientlocale = GetLocale(); 3 | local localStrings = nil; 4 | 5 | --- Add localization 6 | -- @param locale The local ID 7 | -- @param default If true will be used as the default localization 8 | -- @return Table to add localization strings to 9 | function _addon:AddLocalization(locale, default) 10 | if locale ~= clientlocale and (localStrings ~= nil or not default) then 11 | return; 12 | end 13 | 14 | localStrings = setmetatable({}, {__index=function(self, key) 15 | rawset(self, key, key); 16 | print(_addonName .. ": Missing translation for: " .. key); 17 | return key; 18 | end}); 19 | 20 | return localStrings; 21 | end 22 | 23 | --- Get localization table 24 | -- @return Table containing localizations 25 | function _addon:GetLocalization() 26 | return localStrings; 27 | end -------------------------------------------------------------------------------- /images/found.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coolmodi/CChatNotifier/977831de82594b47a62c6ad7f23a6582e3f415a3/images/found.png -------------------------------------------------------------------------------- /images/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coolmodi/CChatNotifier/977831de82594b47a62c6ad7f23a6582e3f415a3/images/ui.png -------------------------------------------------------------------------------- /img/bar.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coolmodi/CChatNotifier/977831de82594b47a62c6ad7f23a6582e3f415a3/img/bar.blp -------------------------------------------------------------------------------- /img/grabber.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coolmodi/CChatNotifier/977831de82594b47a62c6ad7f23a6582e3f415a3/img/grabber.blp -------------------------------------------------------------------------------- /img/grabber_s.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coolmodi/CChatNotifier/977831de82594b47a62c6ad7f23a6582e3f415a3/img/grabber_s.blp -------------------------------------------------------------------------------- /img/iclose.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coolmodi/CChatNotifier/977831de82594b47a62c6ad7f23a6582e3f415a3/img/iclose.blp -------------------------------------------------------------------------------- /img/iplus.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coolmodi/CChatNotifier/977831de82594b47a62c6ad7f23a6582e3f415a3/img/iplus.blp -------------------------------------------------------------------------------- /img/logo.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coolmodi/CChatNotifier/977831de82594b47a62c6ad7f23a6582e3f415a3/img/logo.blp -------------------------------------------------------------------------------- /img/logoo.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coolmodi/CChatNotifier/977831de82594b47a62c6ad7f23a6582e3f415a3/img/logoo.blp -------------------------------------------------------------------------------- /img/logos.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coolmodi/CChatNotifier/977831de82594b47a62c6ad7f23a6582e3f415a3/img/logos.blp -------------------------------------------------------------------------------- /img/off.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coolmodi/CChatNotifier/977831de82594b47a62c6ad7f23a6582e3f415a3/img/off.blp -------------------------------------------------------------------------------- /img/on.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coolmodi/CChatNotifier/977831de82594b47a62c6ad7f23a6582e3f415a3/img/on.blp -------------------------------------------------------------------------------- /img/trash.blp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coolmodi/CChatNotifier/977831de82594b47a62c6ad7f23a6582e3f415a3/img/trash.blp -------------------------------------------------------------------------------- /libs/SettingsCreator.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Simple settings menu builder I made for my addon(s). 3 | Author: https://github.com/coolmodi 4 | Version: 1.0 5 | ]] 6 | 7 | local _addonName, _addon = ...; 8 | 9 | local ROW_V_SPACE = 15; 10 | local DEFAULT_ROW_HEIGHT = 30; 11 | 12 | local rowOffset = 0; 13 | local lastRow = nil; 14 | local rowGroups = {}; 15 | local inputs = {}; 16 | local svTable = nil; 17 | local defaults = nil; 18 | local OnSetCallback = nil; 19 | local AfterSetCallback = nil; 20 | local tempSettings = {}; 21 | 22 | local settings = CreateFrame("FRAME"); 23 | 24 | local vinfo = settings:CreateFontString(nil, nil, 'GameFontDisableSmall'); 25 | vinfo:SetPoint('BOTTOMRIGHT', -10, 6); 26 | vinfo:SetText("Version " .. GetAddOnMetadata(_addonName, "Version") .. " by " .. GetAddOnMetadata(_addonName, "Author")); 27 | 28 | 29 | -------------------------------------------------------------------------------------------------------------------------------- 30 | -- Panel event handlers 31 | -------------------------------------------------------------------------------------------------------------------------------- 32 | 33 | --- Used for panel refresh event 34 | local function OnRefresh(self) 35 | for _, input in pairs(inputs) do 36 | input:RefreshState(); 37 | end 38 | end 39 | 40 | --- Used for panel cancel event 41 | local function OnCancel(self) 42 | wipe(tempSettings); 43 | end 44 | 45 | --- Used for panel reset event 46 | local function OnDefault(self) 47 | wipe(tempSettings); 48 | for k, v in pairs(defaults) do 49 | svTable[k] = v; 50 | end 51 | end 52 | 53 | --- Used for panel save event 54 | local function OnOkay(self) 55 | for k, v in pairs(inputs) do 56 | if v.isEditBox == true then 57 | if v:IsNumeric() then 58 | tempSettings[k] = v:GetNumber(); 59 | else 60 | tempSettings[k] = v:GetText(); 61 | end 62 | end 63 | end 64 | 65 | for k, v in pairs(svTable) do 66 | if tempSettings[k] == nil then 67 | tempSettings[k] = v; 68 | end 69 | end 70 | 71 | if OnSetCallback ~= nil then 72 | OnSetCallback(tempSettings); 73 | end 74 | 75 | for k, v in pairs(tempSettings) do 76 | svTable[k] = v; 77 | end 78 | 79 | wipe(tempSettings); 80 | 81 | if AfterSetCallback ~= nil then 82 | AfterSetCallback(); 83 | end 84 | end 85 | 86 | settings.refresh = OnRefresh; 87 | settings.okay = OnOkay; 88 | settings.cancel = OnCancel; 89 | settings.default = OnDefault; 90 | 91 | -------------------------------------------------------------------------------------------------------------------------------- 92 | -- General functions 93 | -------------------------------------------------------------------------------------------------------------------------------- 94 | 95 | --- Get the settings object 96 | function _addon:GetSettingsBuilder() 97 | return settings; 98 | end 99 | 100 | --- Setup settings panel 101 | -- @param savedVarTable The table in saved variables that stores settings 102 | -- @param defaultSettings A table containing default setting values 103 | -- @param customName If not nil use this as name instead of the addon name 104 | -- @param logoPath Path for a texture to show as logo (optional) 105 | -- @param lw The logo width, used with logoPath 106 | -- @param lh The logo height, used with logoPath 107 | function settings:Setup(savedVarTable, defaultSettings, customName, logoPath, lw, lh, la, lx, ly) 108 | if savedVarTable == nil or defaultSettings == nil then 109 | error("Usage: settings:Setup(savedVarTable, defaultSettings[, customName[, logoPath, logow, logoh]])"); 110 | end 111 | 112 | self.name = customName or _addonName; 113 | InterfaceOptions_AddCategory(self); 114 | 115 | svTable = savedVarTable; 116 | defaults = defaultSettings; 117 | 118 | if logoPath ~= nil then 119 | local logo = settings:CreateTexture (nil, "OVERLAY"); 120 | local la = la or "TOPLEFT"; 121 | local lx = lx or 15; 122 | local ly = ly or -10; 123 | logo:SetPoint(la, settings, la, lx, ly); 124 | logo:SetTexture (logoPath); 125 | logo:SetSize(lw, lh); 126 | rowOffset = lh; 127 | end 128 | end 129 | 130 | --- Setup settings panel 131 | -- @param onSetCb Function to call before settings change, gets table parameter (settingname->value) with the to be set new values 132 | function settings:SetBeforeSaveCallback(onSetCb) 133 | OnSetCallback = onSetCb; 134 | end 135 | 136 | --- Setup settings panel 137 | -- @param afterSetCb Function to call after settings changed 138 | function settings:SetAfterSaveCallback(afterSetCb) 139 | AfterSetCallback = afterSetCb; 140 | end 141 | 142 | --- Get current panel values 143 | -- @returns the table containing current changed values from panel 144 | function settings:GetTempSettings() 145 | return tempSettings; 146 | end 147 | 148 | --- Update row group columns 149 | -- @param groupNum The group number 150 | function settings:UpdateRowGroup(groupNum) 151 | local maxWidths = {}; 152 | 153 | for _, row in pairs(rowGroups[groupNum]) do 154 | for i = 1, row.elementCount, 1 do 155 | if maxWidths[i] == nil or row.elements[i].width > maxWidths[i] then 156 | maxWidths[i] = row.elements[i].width; 157 | end 158 | end 159 | end 160 | 161 | for i = 2, #maxWidths, 1 do 162 | local offset = 0; 163 | for j = 1, i-1, 1 do 164 | offset = offset + maxWidths[j]; 165 | end 166 | 167 | for _, row in pairs(rowGroups[groupNum]) do 168 | if row.elements[i] ~= nil then 169 | row.elements[i].anchorFrame:ClearAllPoints(); 170 | row.elements[i].anchorFrame:SetPoint("LEFT", offset, 0); 171 | end 172 | end 173 | end 174 | end 175 | 176 | 177 | -------------------------------------------------------------------------------------------------------------------------------- 178 | -- Builder functions 179 | -------------------------------------------------------------------------------------------------------------------------------- 180 | 181 | --- Add element to row 182 | -- @param element The frame element to anchor 183 | -- @param width The complete width of the element and everything anchored to it 184 | local function RowAddElement(self, element, width) 185 | self.elementCount = self.elementCount + 1; 186 | self.elements[self.elementCount] = { 187 | width = width + ROW_V_SPACE, 188 | anchorFrame = element 189 | }; 190 | 191 | local offset = 0; 192 | for i = 1, self.elementCount - 1, 1 do 193 | offset = offset + self.elements[i].width; 194 | end 195 | 196 | element:SetPoint("LEFT", offset, 0); 197 | end 198 | 199 | --- Create a row 200 | -- Used to put multiple things into the same row. 201 | -- @param group A number, columns in the same group will be sized to match (optional) 202 | -- @param height Custom height (optional) 203 | -- @return The row object 204 | function settings:MakeSettingsRow(group, height) 205 | local height = height or DEFAULT_ROW_HEIGHT; 206 | 207 | local row = CreateFrame("Frame", nil, self); 208 | row:SetHeight(height); 209 | row.elements = {}; 210 | row.elementCount = 0; 211 | row.AddElement = RowAddElement; 212 | 213 | if lastRow == nil then 214 | row:SetPoint("TOPLEFT", 10, -rowOffset); 215 | row:SetPoint("TOPRIGHT", -10, -rowOffset); 216 | else 217 | row:SetPoint("TOPLEFT", lastRow, "BOTTOMLEFT", 0, 0); 218 | row:SetPoint("TOPRIGHT", lastRow, "BOTTOMRIGHT", 0, 0); 219 | end 220 | 221 | lastRow = row; 222 | 223 | if group ~= nil then 224 | row.group = group; 225 | if rowGroups[group] == nil then 226 | rowGroups[group] = {}; 227 | end 228 | table.insert(rowGroups[group], row); 229 | end 230 | 231 | return row; 232 | end 233 | 234 | 235 | 236 | --- Create a heading row 237 | -- @param titleText The string to show 238 | function settings:MakeHeading(titleText) 239 | local row = self:MakeSettingsRow(nil, 45); 240 | row.label = row:CreateFontString(nil, "OVERLAY", "GameFontNormalMed2"); 241 | row.label:SetPoint("LEFT", 0, -7); 242 | row.label:SetText(titleText); 243 | end 244 | 245 | 246 | 247 | --- Set tooltip for the frame element 248 | -- @param element A frame object 249 | -- @param tooltip The tooltip text 250 | local function SetTooltip(element, tooltip) 251 | element:SetScript("OnEnter", function(self) 252 | GameTooltip:SetOwner(self, "ANCHOR_TOPLEFT"); 253 | GameTooltip:SetText(tooltip, 1, 0.9, 0.9, 1, true); 254 | end); 255 | 256 | element:SetScript("OnLeave", GameTooltip_Hide); 257 | end 258 | 259 | 260 | 261 | --- Checkbox OnClick handler 262 | local function CheckBoxOnClick(self) 263 | ChatConfigFrame_PlayCheckboxSound(self:GetChecked()); 264 | tempSettings[self.settingName] = self:GetChecked(); 265 | end 266 | 267 | --- Refresh checkbox to sv value 268 | local function CheckBoxRefresh(self) 269 | self:SetChecked(svTable[self.settingName]); 270 | end 271 | 272 | --- Create a checkbox option 273 | -- @param settingName The key in the settings saved vars 274 | -- @param labelText The label text 275 | -- @param tooltipText The tooltip text (optional) 276 | -- @param row The row to insert it into (optional) 277 | -- @return the checkbox input object 278 | function settings:MakeCheckboxOption(settingName, labelText, tooltipText, row) 279 | local row = row or self:MakeSettingsRow(); 280 | 281 | local cb = CreateFrame("CheckButton", nil, row); 282 | cb:SetSize(24, 24); 283 | cb.settingName = settingName; 284 | cb.RefreshState = CheckBoxRefresh; 285 | cb:SetScript("OnClick", CheckBoxOnClick); 286 | cb:SetNormalTexture([[Interface\Buttons\UI-CheckBox-Up]]); 287 | cb:SetPushedTexture([[Interface\Buttons\UI-CheckBox-Down]]); 288 | cb:SetHighlightTexture([[Interface\Buttons\UI-CheckBox-Highlight]], "ADD"); 289 | cb:SetCheckedTexture([[Interface\Buttons\UI-CheckBox-Check]]); 290 | cb:SetDisabledCheckedTexture([[Interface\Buttons\UI-CheckBox-Check-Disabled]]); 291 | 292 | local label = cb:CreateFontString(nil, "OVERLAY", "GameFontHighlight"); 293 | label:SetPoint("LEFT", cb, "RIGHT", 7, 0); 294 | label:SetText(labelText); 295 | 296 | cb:SetHitRectInsets(0, -(label:GetStringWidth() + 7), 0, 0); 297 | 298 | if tooltipText then 299 | SetTooltip(cb, tooltipText); 300 | end 301 | 302 | row:AddElement(cb, cb:GetWidth() + label:GetStringWidth() + 7); 303 | 304 | inputs[settingName] = cb; 305 | return cb; 306 | end 307 | 308 | 309 | 310 | --- Refresh editbox to sv value 311 | local function EditBoxRefresh(self) 312 | self:SetText(svTable[self.settingName]); 313 | self:SetCursorPosition(0); 314 | end 315 | 316 | --- Create editbox option 317 | -- @param settingName The key in the settings saved vars 318 | -- @param labelText The label text 319 | -- @param max The max text length 320 | -- @param numeric Is the editbox numeric only 321 | -- @param tooltipText The tooltip text 322 | -- @param row Row to insert it into, if nit row is created (optional) 323 | -- @param forceWidth Force width to this value, if 0 take full width (optional) 324 | -- @param labelWidth Set label to this width instead of string width (optional) 325 | -- @return The editbox frame object 326 | function settings:MakeEditBoxOption(settingName, labelText, max, numeric, tooltipText, row, forceWidth, labelWidth) 327 | local row = row or self:MakeSettingsRow(); 328 | 329 | local label = row:CreateFontString(nil, "OVERLAY", "GameFontNormal"); 330 | label:SetText(labelText); 331 | if labelWidth ~= nil then 332 | label:SetJustifyH("LEFT"); 333 | label:SetWidth(labelWidth); 334 | end 335 | 336 | local edit = CreateFrame("EditBox", nil, row, "InputBoxTemplate"); 337 | edit.settingName = settingName; 338 | edit.RefreshState = EditBoxRefresh; 339 | edit.isEditBox = true; 340 | edit:SetPoint("LEFT", label, "RIGHT", 12, 0); 341 | edit:SetMaxLetters(max); 342 | edit:SetAutoFocus(false); 343 | edit:SetHeight(20); 344 | if numeric then 345 | edit:SetNumeric(true); 346 | end 347 | edit:SetHitRectInsets(-(label:GetWidth() + 12), 0, 0, 0); 348 | 349 | if forceWidth ~= nil then 350 | if forceWidth > 0 then 351 | edit:SetWidth(forceWidth); 352 | else 353 | edit:SetPoint("RIGHT", row, "RIGHT", 0, 0); 354 | end 355 | else 356 | edit:SetWidth(5 + 8*max); 357 | end 358 | 359 | edit:SetScript("OnEnterPressed", EditBox_ClearFocus); 360 | 361 | if tooltipText then 362 | SetTooltip(edit, tooltipText); 363 | end 364 | 365 | row:AddElement(label, edit:GetWidth() + label:GetWidth() + 12 + 2); 366 | 367 | inputs[settingName] = edit; 368 | return edit; 369 | end 370 | 371 | 372 | --- Handler func for slider change 373 | local function OnSliderChange(self, value) 374 | tempSettings[self.settingName] = value; 375 | self.curVal:SetText(value); 376 | end 377 | 378 | --- Handler for slider refresh 379 | local function OnSliderRefresh(self) 380 | self:SetValue(svTable[self.settingName]); 381 | self.curVal:SetText(svTable[self.settingName]); 382 | end 383 | 384 | --- Create editbox option 385 | -- @param settingName The key in the settings saved vars 386 | -- @param labelText The label text 387 | -- @param tooltipText The tooltip text 388 | -- @param min The minimum value 389 | -- @param max The maximum value 390 | -- @param step The step size the slider can be dragged for 391 | -- @param row Row to insert it into, if nit row is created (optional) 392 | -- @return The slider frame object 393 | function settings:MakeSliderOption(settingName, labelText, tooltipText, min, max, step, row) 394 | local row = row or self:MakeSettingsRow(nil, 50); 395 | 396 | local sanchor = CreateFrame("Frame", nil, row); 397 | sanchor:SetSize(1, row:GetHeight()); 398 | 399 | local slider = CreateFrame("Slider", nil, row, "HorizontalSliderTemplate"); 400 | slider.settingName = settingName; 401 | slider.RefreshState = OnSliderRefresh; 402 | slider:SetWidth(175); 403 | slider:SetHeight(17); 404 | slider:SetMinMaxValues(min, max); 405 | slider:SetValueStep(step); 406 | slider:SetObeyStepOnDrag(true); 407 | slider:SetPoint ("LEFT", sanchor, "LEFT", 0, -3); 408 | 409 | local label = slider:CreateFontString(nil, "OVERLAY", "GameFontNormal"); 410 | label:SetText(labelText); 411 | label:SetPoint("BOTTOM", slider, "TOP", 0, 1); 412 | 413 | local minLabel = slider:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); 414 | minLabel:SetText(min); 415 | minLabel:SetPoint("TOPLEFT", slider, "BOTTOMLEFT", 0, 0); 416 | 417 | local maxLabel = slider:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall"); 418 | maxLabel:SetText(max); 419 | maxLabel:SetPoint("TOPRIGHT", slider, "BOTTOMRIGHT", 0, 0); 420 | 421 | 422 | slider.curVal = slider:CreateFontString(nil, "OVERLAY", "GameFontHighlight"); 423 | slider.curVal:SetPoint("TOP", slider, "BOTTOM", 0, 0); 424 | 425 | slider:SetScript("OnValueChanged", OnSliderChange); 426 | 427 | if tooltipText then 428 | SetTooltip(slider, tooltipText); 429 | end 430 | 431 | row:AddElement(sanchor, slider:GetWidth() + slider.curVal:GetWidth() + 7); 432 | 433 | inputs[settingName] = slider; 434 | return slider; 435 | end 436 | 437 | 438 | 439 | --- Create button 440 | -- @param text The button text 441 | -- @param func The function to use on click 442 | -- @param row Row to insert it into, if nit row is created (optional) 443 | -- @return The button frame object 444 | function settings:MakeButton(text, func, row) 445 | local row = row or self:MakeSettingsRow(); 446 | 447 | local button = CreateFrame ("Button", nil, row, "OptionsButtonTemplate"); 448 | button:SetText(text); 449 | button:SetWidth(button:GetTextWidth() + 15); 450 | button:SetScript("OnClick", func); 451 | 452 | row:AddElement(button, button:GetWidth()); 453 | 454 | return button; 455 | end 456 | 457 | 458 | 459 | --- Create row with fontstring 460 | -- @param initialText Initial text to set, height will be set to fit it 461 | -- @param justify The justifyH value (optional) 462 | -- @return the fontstring object 463 | function settings:MakeStringRow(initialText, justify) 464 | local row = self:MakeSettingsRow(nil, 400); 465 | local fstring = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight"); 466 | fstring:SetAllPoints(); 467 | 468 | if justify ~= nil then 469 | fstring:SetJustifyH(justify); 470 | end 471 | 472 | fstring:SetSpacing(2); 473 | fstring:SetText(initialText); 474 | 475 | local height = fstring:GetStringHeight(); 476 | if height < DEFAULT_ROW_HEIGHT then 477 | height = DEFAULT_ROW_HEIGHT; 478 | end 479 | row:SetHeight(height); 480 | 481 | return fstring; 482 | end 483 | 484 | 485 | 486 | -- Hanlde dropdown refresh 487 | local function DropdownRefresh(self) 488 | local optionName = "NOT SET!"; 489 | for k,v in pairs(self.GetListItems()) do 490 | if k == svTable[self.settingName] then 491 | optionName = v; 492 | break; 493 | end 494 | end 495 | UIDropDownMenu_SetText(self, optionName); 496 | end; 497 | 498 | local function DropdownOpen(self, level, menuList) 499 | local info = UIDropDownMenu_CreateInfo(); 500 | info.func = function(selfb, arg1, arg2) 501 | tempSettings[self.settingName] = arg1; 502 | UIDropDownMenu_SetText(self, arg2); 503 | end; 504 | for k, v in pairs(self.GetListItems()) do 505 | info.text = v; 506 | info.arg1 = k; 507 | info.arg2 = v; 508 | if tempSettings[self.settingName] ~= nil then 509 | info.checked = (k == tempSettings[self.settingName]); 510 | else 511 | info.checked = (k == svTable[self.settingName]); 512 | end 513 | UIDropDownMenu_AddButton(info); 514 | end 515 | end 516 | 517 | --- Create dropdown 518 | -- @param settingName The key in the settings saved vars 519 | -- @param labelText The label text 520 | -- @param tooltipText The tooltip text 521 | -- @param width The width of the dropdown 522 | -- @param func The function to get list items from (value is displayed name) 523 | -- @param labelWidth Set label to static width, ignore string width (optional) 524 | -- @param row Row to insert it into, if nit row is created (optional) 525 | -- @return The button frame object 526 | function settings:MakeDropdown(settingName, labelText, tooltipText, width, func, labelWidth, row) 527 | local row = row or self:MakeSettingsRow(); 528 | 529 | local label = row:CreateFontString(nil, "OVERLAY", "GameFontNormal"); 530 | label:SetText(labelText); 531 | if labelWidth then 532 | label:SetJustifyH("LEFT"); 533 | label:SetWidth(labelWidth); 534 | end 535 | 536 | local dropDown = CreateFrame("Frame", nil, row, "UIDropDownMenuTemplate"); 537 | dropDown.settingName = settingName; 538 | dropDown.RefreshState = DropdownRefresh; 539 | dropDown.GetListItems = func; 540 | dropDown.Text:SetJustifyH("LEFT"); 541 | dropDown:SetPoint("LEFT", label, "RIGHT", -3, 0); 542 | UIDropDownMenu_SetWidth(dropDown, width); 543 | UIDropDownMenu_Initialize(dropDown, DropdownOpen); 544 | 545 | if tooltipText then 546 | SetTooltip(dropDown, tooltipText); 547 | end 548 | 549 | -- TODO: width is a bit strange on the dropdown template, fix when needed 550 | row:AddElement(label, label:GetWidth() + dropDown:GetWidth() - 15); 551 | 552 | inputs[settingName] = dropDown; 553 | return dropDown; 554 | end -------------------------------------------------------------------------------- /main.lua: -------------------------------------------------------------------------------- 1 | local _addonName, _addon = ...; 2 | local L = _addon:GetLocalization(); 3 | 4 | local frame = CreateFrame("Frame"); 5 | local handlers = {}; 6 | local playerName = UnitName("player"); 7 | 8 | --- Add new entry to the list 9 | -- @param search The string to search for 10 | function _addon:AddToList(search) 11 | local ntable = { 12 | active = true, 13 | words = {} 14 | }; 15 | 16 | for found in string.gmatch(search, "([^,]+)") do 17 | table.insert(ntable.words, strtrim(found):lower()); 18 | end 19 | 20 | CChatNotifier_data[search] = ntable; 21 | _addon:MainUI_UpdateList(); 22 | end 23 | 24 | --- Remove entry from list 25 | -- @param search The string to remove 26 | function _addon:RemoveFromList(search) 27 | CChatNotifier_data[search] = nil; 28 | _addon:MainUI_UpdateList(); 29 | end 30 | 31 | --- Toggle entry active state 32 | -- @param search The search string to toggle 33 | -- @return the new state 34 | function _addon:ToggleEntry(search) 35 | if CChatNotifier_data[search] ~= nil then 36 | CChatNotifier_data[search].active = not CChatNotifier_data[search].active; 37 | return CChatNotifier_data[search].active; 38 | end 39 | return false; 40 | end 41 | 42 | --- Clear the whole list 43 | function _addon:ClearList() 44 | wipe(CChatNotifier_data); 45 | _addon:MainUI_UpdateList(); 46 | end 47 | 48 | --- Form notification msg from msg format template 49 | -- @param search The found keyword 50 | -- @param source The source of the message 51 | -- @param from The player it is from 52 | -- @param msg The message from chat 53 | -- @param searchstart Start position of found keyword in message 54 | -- @param searchend End position of found keyword in message 55 | -- @return The finished message string 56 | function _addon:FormNotifyMsg(search, source, from, msg, searchstart, searchend) 57 | local formed = CChatNotifier_settings.outputFormat; 58 | 59 | -- Default color 60 | local fstart, fend = string.find(formed, "<<%x%x%x%x%x%x>>"); 61 | local defaultColor = "|r"; 62 | if fstart ~= nil then 63 | defaultColor = "|cFF" .. string.sub(formed, fstart+2, fend-2); 64 | formed = string.gsub(formed, "<<%x%x%x%x%x%x>>", defaultColor); 65 | end 66 | formed = string.gsub(formed, "<>", defaultColor); 67 | 68 | -- Colors 69 | fstart, fend = string.find(formed, "<%x%x%x%x%x%x>"); 70 | while fstart ~= nil do 71 | formed = string.gsub(formed, string.sub(formed, fstart, fend), "|cFF"..string.sub(formed, fstart+1, fend-1)); 72 | fstart, fend = string.find(formed, "<%x%x%x%x%x%x>"); 73 | end 74 | 75 | -- remove server dash 76 | local dashLoc = string.find(from, "-"); 77 | if dashLoc ~= nil then 78 | from = string.sub(from, 1, dashLoc-1); 79 | end 80 | 81 | -- Placeholders 82 | formed = string.gsub(formed, "{K}", search); 83 | formed = string.gsub(formed, "{S}", source); 84 | formed = string.gsub(formed, "{P}", string.format("|Hplayer:%s|h%s|h", from, from)); 85 | 86 | if searchstart > 1 then 87 | formed = string.gsub(formed, "{MS}", string.sub(msg, 1, searchstart-1)); 88 | else 89 | formed = string.gsub(formed, "{MS}", ""); 90 | end 91 | 92 | formed = string.gsub(formed, "{MF}", string.sub(msg, searchstart, searchend)); 93 | 94 | if searchend < msg:len() then 95 | formed = string.gsub(formed, "{ME}", string.sub(msg, searchend+1, msg:len())); 96 | else 97 | formed = string.gsub(formed, "{ME}", ""); 98 | end 99 | 100 | local hours, minutes = GetGameTime(); 101 | if hours < 10 then hours = "0" .. hours; end 102 | if minutes < 10 then minutes = "0" .. minutes; end 103 | formed = string.gsub(formed, "{T}", hours..":"..minutes); 104 | 105 | return formed; 106 | end 107 | 108 | --- Output message to set chatframe 109 | -- @param notiMsg The message to post to chat 110 | -- @param frameNum The chat tab to output to 111 | function _addon:PostNotification(notiMsg, frameNum) 112 | if strtrim(notiMsg):len() == 0 then 113 | _addon:PrintError(L["ERR_NOTIFY_FORMAT_MISSING"]); 114 | else 115 | _G["ChatFrame"..frameNum]:AddMessage(notiMsg); 116 | end 117 | 118 | if CChatNotifier_settings.soundId ~= "" then 119 | PlaySoundFile(CChatNotifier_settings.soundId, "Master"); 120 | end 121 | 122 | FCF_StartAlertFlash(_G["ChatFrame"..frameNum]); 123 | end 124 | 125 | --- Remove server names from names given as "Character-Servername" 126 | -- @param name The name to remove the dash server part from 127 | local function RemoveServerDash(name) 128 | local dash = name:find("-"); 129 | if dash then 130 | return name:sub(1, dash-1); 131 | end 132 | return name; 133 | end 134 | 135 | --- Search message for searched terms 136 | -- If one is found then trigger notification. 137 | -- @param msg The message to search in 138 | -- @param from The player it is from 139 | -- @param source The source of the message (SAY, CHANNEL) 140 | -- @param channelName If source is CHANNEL this is the channel name 141 | local function SearchMessage(msg, from, source) 142 | local msglow = string.lower(msg); 143 | local fstart, fend; 144 | for _, data in pairs(CChatNotifier_data) do 145 | if data.active then 146 | for _, search in ipairs(data.words) do 147 | fstart, fend = string.find(msglow, search); 148 | if fstart ~= nil then 149 | local nameNoDash = RemoveServerDash(from); 150 | if nameNoDash == playerName then 151 | return; 152 | end 153 | _addon:PostNotification(_addon:FormNotifyMsg(search, source, from, msg, fstart, fend), CChatNotifier_settings.chatFrame); 154 | return; 155 | end 156 | end 157 | end 158 | end 159 | end 160 | 161 | --- Set addon state to current SV value 162 | local function UpdateAddonState() 163 | if CChatNotifier_settings.isActive then 164 | frame:RegisterEvent("CHAT_MSG_SAY"); 165 | frame:RegisterEvent("CHAT_MSG_YELL"); 166 | frame:RegisterEvent("CHAT_MSG_CHANNEL"); 167 | else 168 | frame:UnregisterEvent("CHAT_MSG_SAY"); 169 | frame:UnregisterEvent("CHAT_MSG_YELL"); 170 | frame:UnregisterEvent("CHAT_MSG_CHANNEL"); 171 | end 172 | _addon:MinimapButtonUpdate(); 173 | end 174 | 175 | --- Toggle search on/off 176 | function _addon:ToggleAddon() 177 | CChatNotifier_settings.isActive = not CChatNotifier_settings.isActive; 178 | UpdateAddonState(); 179 | end 180 | 181 | 182 | ------------------------------------------------ 183 | -- Events 184 | ------------------------------------------------ 185 | 186 | function handlers.ADDON_LOADED(addonName) 187 | if addonName ~= _addonName then 188 | return; 189 | end 190 | frame:UnregisterEvent("ADDON_LOADED"); 191 | _addon:SetupSettings(); 192 | _addon:MainUI_UpdateList(); 193 | UpdateAddonState(); 194 | 195 | if CChatNotifier_settings.firstStart then 196 | _addon:MainUI_OpenList(); 197 | print(L["FIRST_START_MSG"]); 198 | CChatNotifier_settings.firstStart = false; 199 | CChatNotifier_settings.outputFormat = L["CHAT_NOTIFY_FORMAT"]; 200 | end 201 | end 202 | 203 | function handlers.CHAT_MSG_CHANNEL(text, playerName, _, channelName) 204 | SearchMessage(text, playerName, channelName); 205 | end 206 | 207 | function handlers.CHAT_MSG_SAY(text, playerName) 208 | SearchMessage(text, playerName, L["VICINITY"]); 209 | end 210 | 211 | function handlers.CHAT_MSG_YELL(text, playerName) 212 | SearchMessage(text, playerName, L["VICINITY"]); 213 | end 214 | 215 | frame:SetScript( "OnEvent",function(self, event, ...) 216 | handlers[event](...); 217 | end) 218 | 219 | frame:RegisterEvent("ADDON_LOADED"); 220 | 221 | 222 | ------------------------------------------------ 223 | -- Slash command 224 | ------------------------------------------------ 225 | 226 | SLASH_CCHATNOTIFIER1 = "/ccn"; 227 | SlashCmdList["CCHATNOTIFIER"] = function(arg) 228 | _addon:MainUI_OpenList(); 229 | end; 230 | 231 | 232 | ------------------------------------------------ 233 | -- Helper 234 | ------------------------------------------------ 235 | 236 | --- Print error message (red) 237 | -- @param msg The message to print 238 | function _addon:PrintError(msg) 239 | print("|cFFFF3333" .. _addonName .. ": " .. msg:gsub("|r", "|cFFFF3333")); 240 | end -------------------------------------------------------------------------------- /settings.lua: -------------------------------------------------------------------------------- 1 | local _addonName, _addon = ...; 2 | local L = _addon:GetLocalization(); 3 | 4 | local DEFAULTSETTINGS = { 5 | ["firstStart"] = true, 6 | ["isActive"] = true, 7 | ["chatFrame"] = 1, 8 | ["soundId"] = "sound/interface/itellmessage.ogg", 9 | ["showMinimapButton"] = true, 10 | ["snapToMinimap"] = true, 11 | ["outputFormat"] = "", -- fill from localization 12 | ["version"] = GetAddOnMetadata(_addonName, "Version") 13 | }; 14 | 15 | local SOUNDS = { 16 | [""] = L["SOUND_NO_SOUND"], 17 | ["sound/Doodad/LightHouseFogHorn.ogg"] = "Fog horn", -- 567094 18 | ["sound/interface/itellmessage.ogg"] = "Whisper", -- 567421 19 | ["sound/character/dwarf/dwarfmale/dwarfmaledeatha.ogg"] = "Dwarf", -- 539885 20 | ["sound/item/weapons/bow/arrowhitc.ogg"] = "Something", -- 567671 21 | ["sound/item/weapons/bow/arrowhita.ogg"] = "Something2", -- 567672 22 | ["sound/item/weapons/axe2h/m2haxehitmetalweaponcrit.ogg"] = "Hurts my ears" -- 567653 23 | }; 24 | 25 | --- Handle stuff after settings changed, if needed 26 | local function AfterSettingsChange() 27 | _addon:MinimapButtonUpdate(); 28 | if CChatNotifier_settings.snapToMinimap then 29 | _addon:MinimapButtonSnap(); 30 | end 31 | end 32 | 33 | --- Setup SV tables, check settings and setup settings menu 34 | function _addon:SetupSettings() 35 | if CChatNotifier_data == nil then 36 | CChatNotifier_data = {}; 37 | end 38 | 39 | if CChatNotifier_settings == nil then 40 | CChatNotifier_settings = DEFAULTSETTINGS; 41 | end 42 | 43 | for k, v in pairs(DEFAULTSETTINGS) do 44 | if CChatNotifier_settings[k] == nil then 45 | CChatNotifier_settings[k] = v; 46 | end 47 | end 48 | for k, v in pairs(CChatNotifier_settings) do 49 | if DEFAULTSETTINGS[k] == nil then 50 | CChatNotifier_settings[k] = nil; 51 | end 52 | end 53 | 54 | local settings = _addon:GetSettingsBuilder(); 55 | settings:Setup(CChatNotifier_settings, DEFAULTSETTINGS, nil, [[Interface\AddOns\CChatNotifier\img\logos]], 192, 48, nil, 16); 56 | settings:SetAfterSaveCallback(AfterSettingsChange); 57 | 58 | settings:MakeHeading(L["SETTINGS_HEAD_GENERAL"]); 59 | 60 | settings:MakeDropdown("chatFrame", L["SETTINGS_CHATFRAME"], L["SETTINGS_CHATFRAME_TT"], 100, function() 61 | local chatWindows = {}; 62 | for i = 1, NUM_CHAT_WINDOWS, 1 do 63 | local name, _, _, _, _, _, shown, _, docked = GetChatWindowInfo(i); 64 | if name ~= "" and (shown or docked) then 65 | chatWindows[i] = name; 66 | end 67 | end 68 | return chatWindows; 69 | end, 138); 70 | 71 | settings:MakeDropdown("soundId", L["SETTINGS_SOUNDID"], L["SETTINGS_SOUNDID_TT"], 100, function() 72 | return SOUNDS; 73 | end, 138); 74 | 75 | local row = settings:MakeSettingsRow(); 76 | settings:MakeCheckboxOption("showMinimapButton", L["SETTINGS_MINIMAP"], L["SETTINGS_MINIMAP_TT"], row); 77 | settings:MakeCheckboxOption("snapToMinimap", L["SETTINGS_SNAP_MINIMAP"], L["SETTINGS_SNAP_MINIMAP_TT"], row); 78 | 79 | settings:MakeHeading(L["SETTINGS_HEAD_FORMAT"]); 80 | settings:MakeStringRow(L["SETTINGS_FORMAT_DESC"], "LEFT"); 81 | 82 | local formatEdit = settings:MakeEditBoxOption("outputFormat", nil, 200, false, nil, nil, 0); 83 | local prevString = settings:MakeStringRow(); 84 | formatEdit:SetScript("OnTextChanged", function(self) 85 | local oldFormat = CChatNotifier_settings.outputFormat; 86 | CChatNotifier_settings.outputFormat = formatEdit:GetText(); 87 | local preview = _addon:FormNotifyMsg("mankrik", "1. General", GetUnitName("player"), "LFM mankriks wife exploration team!", 5, 11); 88 | prevString:SetText(preview); 89 | CChatNotifier_settings.outputFormat = oldFormat; 90 | end); 91 | 92 | row = settings:MakeSettingsRow(); 93 | 94 | settings:MakeButton(L["SETTINGS_TEST_CHAT"], function() 95 | local oldSound = CChatNotifier_settings.soundId; 96 | local oldFormat = CChatNotifier_settings.outputFormat; 97 | CChatNotifier_settings.outputFormat = formatEdit:GetText(); 98 | if settings:GetTempSettings().soundId then 99 | CChatNotifier_settings.soundId = settings:GetTempSettings().soundId; 100 | end 101 | _addon:PostNotification(_addon:FormNotifyMsg("mankrik", L["VICINITY"], GetUnitName("player"), 102 | "LFM mankriks wife exploration team!", 5, 11), settings:GetTempSettings().chatFrame or CChatNotifier_settings.chatFrame); 103 | CChatNotifier_settings.soundId = oldSound; 104 | CChatNotifier_settings.outputFormat = oldFormat; 105 | end, row); 106 | 107 | settings:MakeButton(L["SETTINGS_FORMAT_RESET"], function() 108 | CChatNotifier_settings.outputFormat = L["CHAT_NOTIFY_FORMAT"]; 109 | formatEdit:SetText(CChatNotifier_settings.outputFormat); 110 | formatEdit:SetCursorPosition(0); 111 | end, row); 112 | end --------------------------------------------------------------------------------