Nenue@50: --- Devian - UI.lua Nenue@35: -- @file-author@ Nenue@35: -- @project-revision@ @project-hash@ Nenue@35: -- @file-revision@ @file-hash@ Nenue@35: -- Created: 12/27/2015 3:01 AM Nenue@35: if not LibStub then Nenue@35: print('Something has happened...') Nenue@35: end Nenue@66: local _, D = ... Nenue@35: local DEVIAN_FRAME = 'DevianConsole' Nenue@66: local insert, tonumber, pairs, concat = tinsert, tonumber, pairs, table.concat Nenue@66: local L = D.L Nenue@66: local print = D.print Nenue@66: Nenue@66: Nenue@66: Nenue@66: Nenue@66: local Console_OnMovementChanged = function(self, event) Nenue@66: local db = D.db Nenue@66: if self.enabled then Nenue@66: if event == 'PLAYER_STARTED_MOVING' then Nenue@66: self.moveFade:Stop() Nenue@66: local F1 = self.moveFade.alphaOut Nenue@66: F1:SetFromAlpha(db.movement_fade_from) Nenue@66: F1:SetToAlpha(db.movement_fade_to) Nenue@66: F1:SetDuration(db.movement_fade_time) Nenue@66: self.moveFade:Play() Nenue@66: self:EnableMouse(false) Nenue@66: else Nenue@66: self.moveFade:Stop() Nenue@66: local F1 = self.moveFade.alphaOut Nenue@66: F1:SetToAlpha(db.movement_fade_from) Nenue@66: F1:SetFromAlpha(db.movement_fade_to) Nenue@66: F1:SetDuration(db.movement_fade_time) Nenue@66: self.moveFade:Play() Nenue@66: self:EnableMouse(true) Nenue@66: end Nenue@66: end Nenue@66: end Nenue@66: Nenue@35: Nenue@35: Nenue@35: local function Console_MinMax(self) Nenue@35: if self.minimized then Nenue@35: self:Maximize() Nenue@35: else Nenue@35: self:Minimize() Nenue@35: end Nenue@35: end Nenue@35: Nenue@35: local function Console_Minimize(self) Nenue@35: self:SetHeight(20) Nenue@35: self:SetMaxResize(GetScreenWidth(),20) Nenue@35: self.minimized = true Nenue@35: self.out:Hide() Nenue@35: self:Save() Nenue@35: end Nenue@35: Nenue@35: local function Console_Maximize(self) Nenue@35: local db = D.channels[self.index] Nenue@35: self:SetHeight(db.height) Nenue@35: self:SetMaxResize(GetScreenWidth(),GetScreenHeight()) Nenue@35: self.minimized = nil Nenue@35: self.out:Show() Nenue@35: self:Save() Nenue@35: end Nenue@35: Nenue@35: Nenue@35: local function Console_Save(self) Nenue@70: local db = D.currentProfile.channels[self.index] Nenue@35: db.x = self:GetLeft() Nenue@35: db.y = (self:GetTop() - GetScreenHeight()) Nenue@35: db.width = self:GetWidth() Nenue@35: Nenue@35: if not self.minimized then Nenue@55: db.height = self:GetHeight() Nenue@35: self:SetHeight(db.height) Nenue@35: end Nenue@35: Nenue@35: db.dockedTo = self.dockedTo Nenue@35: db.docked = self.docked Nenue@35: Nenue@70: db.minimized = self.minimized Nenue@70: db.enabled = self.enabled Nenue@70: db.active = self.active Nenue@35: self:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', db.x, db.y) Nenue@35: self:SetWidth(db.width) Nenue@35: end Nenue@35: Nenue@35: --- Brings the console to the front. Nenue@35: -- Frame method used to bring a console frame to the front of the display stack. Nenue@35: local function Console_ToFront(c) Nenue@35: local db = D.db Nenue@68: local profile = D.currentProfile Nenue@35: c:Raise() Nenue@35: c:SetAlpha(db.frontalpha) Nenue@83: c.out.backdrop:SetColorTexture(unpack(db.frontdrop)) Nenue@35: c.out.backdrop:SetGradientAlpha(unpack(db.frontgrad)) Nenue@35: c.out.backdrop:SetBlendMode(db.frontblend) Nenue@45: c.dropmenu.icon:SetVertexColor(unpack(db.frontheader)) Nenue@45: c.title:SetTextColor(unpack(db.frontborder)) Nenue@60: Nenue@62: --oldprint('changing current toplevel from', db.current_channel, 'to', c.index) Nenue@68: profile.current_channel = c.index Nenue@35: Nenue@62: --oldprint('toplevel is now', db.current_channel) Nenue@60: c:Save() Nenue@60: Nenue@60: Nenue@50: -- update dock buttons Nenue@50: local beacon = D.dock.buttons[c.index] Nenue@50: beacon.selected = true Nenue@58: beacon.newMessage = nil Nenue@50: D.UpdateBeacon(beacon) Nenue@50: Nenue@35: for _, part in pairs(c.border) do Nenue@83: part:SetColorTexture(unpack(db.frontborder)) Nenue@35: end Nenue@35: Nenue@35: for id, bc in pairs(D.console) do Nenue@35: if id ~= c.index then Nenue@35: bc:SetAlpha(db.backalpha) Nenue@83: bc.out.backdrop:SetColorTexture(unpack(db.backdrop)) Nenue@35: bc.out.backdrop:SetGradientAlpha(unpack(db.backgrad)) Nenue@35: bc.out.backdrop:SetBlendMode(db.backblend) Nenue@45: bc.dropmenu.icon:SetVertexColor(unpack(db.backheader)) Nenue@36: bc.title:SetTextColor(unpack(db.backborder)) Nenue@35: Nenue@50: local beacon = D.dock.buttons[bc.index] Nenue@58: beacon.raised = nil Nenue@58: beacon.showName = nil Nenue@50: beacon.selected = nil Nenue@50: D.UpdateBeacon(beacon) Nenue@50: Nenue@35: for _, part in pairs(bc.border) do Nenue@83: part:SetColorTexture(unpack(db.backborder)) Nenue@35: end Nenue@35: end Nenue@35: end Nenue@35: end Nenue@35: Nenue@35: local function Console_MouseDown(self, button, up) Nenue@35: if button == 'LeftButton' then Nenue@35: if up then Nenue@35: self:StopMovingOrSizing() Nenue@35: self:ToFront() Nenue@35: self:Save() Nenue@35: elseif self.out.grip:IsMouseOver() then Nenue@35: self:StartSizing() Nenue@35: else Nenue@35: self:StartMoving() Nenue@35: end Nenue@35: else Nenue@35: if up then Nenue@35: self:MinMax() Nenue@35: end Nenue@35: end Nenue@35: end Nenue@35: local function Console_MouseUp(self, button) Nenue@35: return Console_MouseDown(self, button, true) Nenue@35: end Nenue@35: Nenue@35: Nenue@35: --- Constructs the frame object for a console channel Nenue@35: -- Initializes the console channel at a specified index. Nenue@35: -- Configuration data can be overridden by passing a desired settings table. Nenue@35: -- @param i Numeric index of the channel as it manifests in db.channels Nenue@35: -- @param vars Optional settings table to be used. Nenue@35: local function CreateConsole(i, vars) Nenue@35: local db = D.db Nenue@35: if tonumber(i) == nil or math.floor(i) ~= i then Nenue@35: error('Non-integer index value.') Nenue@35: end Nenue@35: if not vars then Nenue@35: vars = D.channels[i] and D.channels[i] or D.channels[db.primary_channel] Nenue@35: end Nenue@35: local f Nenue@70: f = CreateFrame('Frame', 'DevianChannelFrame' .. i, UIParent, DEVIAN_FRAME) Nenue@47: Nenue@35: --@debug@ Nenue@35: --print(f:GetName()) Nenue@35: Nenue@35: --print('create(2)') Nenue@35: for k,v in pairs(vars) do Nenue@35: f[k] = v Nenue@35: --@debug@ Nenue@36: --print(' f['..type(k)..' '..tostring(k)..'] = '..type(v)..' '..tostring(v)) Nenue@35: end Nenue@35: Nenue@35: f:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', vars.x, vars.y) Nenue@35: f:SetSize(vars.width, vars.height) Nenue@35: f:Lower() Nenue@35: f.out:SetFont(db.font, db.fontsize, db.fontoutline) Nenue@35: if (db.current_channel == i) then Nenue@83: f.out.backdrop:SetColorTexture(unpack(db.frontdrop)) Nenue@36: f.dropmenu.icon:SetVertexColor(unpack(db.headerfontcolor)) Nenue@36: f.title:SetTextColor(unpack(db.headerfontcolor)) Nenue@45: f.header:SetAlpha(db.headeralpha) Nenue@35: else Nenue@83: f.out.backdrop:SetColorTexture(unpack(db.backdrop)) Nenue@35: end Nenue@35: Nenue@35: f.Save = Console_Save Nenue@35: f.Minimize = Console_Minimize Nenue@35: f.Maximize = Console_Maximize Nenue@35: f.MinMax = Console_MinMax Nenue@35: f.ToFront = Console_ToFront Nenue@35: f.Toggle = D.Console_Toggle Nenue@35: f:SetScript('OnMouseDown', Console_MouseDown) Nenue@35: f:SetScript('OnMouseUp', Console_MouseUp) Nenue@66: f.profileID = db.current_profile Nenue@35: Nenue@36: Nenue@36: UIDropDownMenu_Initialize(f.menuFrame, function() Nenue@36: local info = { { Nenue@36: text= "Close", Nenue@36: value = "OptClose", Nenue@36: func = function () Nenue@36: f.enabled = nil Nenue@36: f:Hide() Nenue@36: f:Save() Nenue@38: end },--[[ Nenue@36: { Nenue@36: text = "Dock", Nenue@36: value = "OptDock", Nenue@38: func = function() print('Dvn', 'docking shenanary') end }]] Nenue@36: } Nenue@36: for _, v in ipairs(info) do Nenue@36: UIDropDownMenu_AddButton(v) Nenue@36: end Nenue@36: end, 'MENU') Nenue@36: Nenue@66: if db.movement_fade then Nenue@66: f:RegisterEvent('PLAYER_STARTED_MOVING') Nenue@66: f:RegisterEvent('PLAYER_STOPPED_MOVING') Nenue@66: f:SetScript('OnEvent', Console_OnMovementChanged) Nenue@66: end Nenue@66: Nenue@47: D.dock.buttons[i] = CreateFrame('Button', 'Channel'..i..'Beacon', UIParent, 'DevianBeacon') Nenue@47: D.dock.buttons[i].icon:SetVertexColor(math.random(),math.random(),math.random()) Nenue@47: D.dock.buttons[i].console = f Nenue@47: D.dock.buttons[i].index = i Nenue@47: D.dock.buttons[i].caption.name:SetText(vars.signature) Nenue@47: D.dock.buttons[i]:Show() Nenue@47: Nenue@35: if vars.minimized then Nenue@35: f:Minimize() Nenue@35: else Nenue@35: f:Maximize() Nenue@35: end Nenue@68: if db.enabled then Nenue@68: f.enabled = true Nenue@35: f:Show() Nenue@35: end Nenue@35: Nenue@35: return f Nenue@35: end Nenue@35: Nenue@35: Nenue@35: --- Updates console information and returns the handle of the channel object that was worked on. Nenue@35: -- When key is nil or not a valid handle, a new channel is created using whatever signature can be found in cinfo. Nenue@35: -- The signature can be passed as a string, or as a table entry under the key 'signature' Nenue@35: -- If the signature of a new channel is also a tag, the channel will be added to that tag Nenue@35: -- @param cinfo string signature of a new channel, or a table of config variables to be imposed on the channel Nenue@35: -- @param key string signature or index number of channel to operate on Nenue@35: -- @usage channel = D:SetChannel('new', nil) -- creates a new channel Nenue@35: -- @usage channel = D:SetChannel({x = 200, y = 100}, 4) -- updates channel #4 Nenue@35: function D:SetChannel(cinfo, key) Nenue@66: local profile = D.currentProfile Nenue@35: local t_info = {} Nenue@35: local channel, isNew, id, sig, t_id Nenue@36: --@debug@ Nenue@68: --print('setchan(0) cinfo, key', cinfo, key)--@end-debug@ Nenue@35: -- obtain source data Nenue@66: if tonumber(key) ~= nil and D.channels[key] then Nenue@35: id = tonumber(key) Nenue@35: elseif D.sigID[tostring(key)] then Nenue@35: id = D.sigID[tostring(key)] Nenue@35: else Nenue@66: id = profile.default_channel Nenue@35: isNew = true Nenue@35: end Nenue@66: local dbvars = D.channels[id] Nenue@35: t_id = id -- overridden later if new Nenue@35: t_info.index = t_id -- Nenue@35: --@debug@ Nenue@68: --print('setchan(1) cinfo, key, id=', cinfo, key, id)--@end-debug@ Nenue@35: Nenue@35: Nenue@35: -- obtain config info Nenue@35: if type(cinfo) == 'string' then Nenue@35: sig = cinfo Nenue@35: cinfo = {signature = sig} Nenue@35: elseif type(cinfo) ~= 'table' then -- stop here if a table wans't passed Nenue@66: error('Expecting table of string as arg1') Nenue@35: elseif cinfo.signature then -- new sig Nenue@66: sig = cinfo.signature Nenue@35: elseif isNew then -- new channel sig Nenue@66: sig = 'Ch' Nenue@35: else -- old sig Nenue@66: sig = D.channels[id].signature Nenue@35: end Nenue@35: t_info.signature = sig Nenue@35: --@debug@ Nenue@68: --print('setchan(2) sig,id,isNew=', sig, id, isNew)--@end-debug@ Nenue@35: Nenue@35: for k,v in pairs(cinfo) do -- allow all cinfo to pass Nenue@35: t_info[k] = v Nenue@35: end Nenue@35: Nenue@35: local blocked = { -- ignore these vars: Nenue@35: ['docked'] = true, -- table Nenue@35: ['dockedTo'] = true, -- table-related Nenue@35: ['signature'] = true} -- already determined Nenue@35: for k,v in pairs(dbvars) do Nenue@35: if not t_info[k] and not blocked[k] then -- already set or blocked? Nenue@70: --print('assign', k, '=', v) Nenue@35: t_info[k] = v Nenue@35: end Nenue@35: end Nenue@35: -- new channel overrides Nenue@35: if isNew then Nenue@72: if D.sigID[sig] then -- find a non-clashing signature Nenue@35: local result, i = sig, 1 Nenue@35: while D.sigID[result] do Nenue@35: result = sig .. i Nenue@35: i = i + 1 Nenue@35: end Nenue@35: t_info.signature = result Nenue@35: end Nenue@36: t_id = self.max_channel + 1 Nenue@35: t_info.index = t_id Nenue@72: Nenue@72: self.max_channel = t_id Nenue@35: --@debug@ Nenue@68: --print('setchan(3a) t_id, isNew, sig, t_info.signature=', t_id, isNew, sig, t_info.signature)--@end-debug@ Nenue@35: else Nenue@35: --@debug@ Nenue@68: --print('setchan(3b) t_id, isNew, sig, t_info.signature=', t_id, isNew, sig, t_info.signature)--@end-debug@ Nenue@35: end Nenue@35: Nenue@35: local channel Nenue@35: if not self.console[t_id] then -- create a frame Nenue@66: if isNew then -- position the channel frame Nenue@66: profile.max_channel = t_id Nenue@66: t_info.x = t_info.x + 20 Nenue@66: t_info.y = t_info.y - 20 Nenue@66: profile.channels[t_id] = t_info Nenue@66: --@debug@ Nenue@68: --print('setchan(4a)', 't_id, x, y=', t_id, t_info.x, t_info.y)--@end-debug@ Nenue@66: end Nenue@66: channel = CreateConsole(t_id, t_info) Nenue@66: self.console[t_id] = channel Nenue@66: self.sig[t_info.signature] = channel Nenue@66: self.sigID[t_info.signature] = t_id Nenue@66: self.IDsig[t_id] = t_info.signature Nenue@35: end Nenue@35: channel = self.console[t_id] Nenue@35: if channel.minimized then Nenue@35: channel:Minimize() Nenue@35: else Nenue@35: channel:Maximize() Nenue@35: end Nenue@35: Nenue@55: if channel.enabled then -- hide or show last since Min/Max mess with visibility Nenue@70: --print('setchan(5a) enable') Nenue@55: channel:Show() Nenue@60: --channel:ToFront() Nenue@35: else Nenue@68: --print('setchan(5a) disable') Nenue@35: channel:Hide() Nenue@35: end Nenue@35: --@debug@ Nenue@68: --print('setchan(end); c:IsVisible(), c.enabled, db.enabled=', channel:IsVisible(), channel.enabled, profile.enabled)--@end-debug@ Nenue@35: return channel Nenue@66: end Nenue@66: Nenue@66: --- Console frame toggler Nenue@66: -- @paramsig [...] Nenue@66: -- @param ... one or more space-seperated channel keys Nenue@87: function D:Console_Toggle(cmd, force) Nenue@87: Nenue@87: Nenue@88: local search = {} Nenue@87: if cmd then Nenue@87: cmd = tostring(cmd) Nenue@87: local i, j = 0, 0 Nenue@87: repeat Nenue@87: i, j = cmd:find("%S+", j+1) Nenue@87: if i and j then Nenue@87: local key = cmd:sub(i, j) Nenue@87: if self.sig[key] then Nenue@87: --print(key, self.sigID[key]) Nenue@87: insert(search, self.sigID[key]) Nenue@87: elseif self.console[tonumber(key)] then Nenue@87: --print(key, tonumber(key)) Nenue@87: insert(search, tonumber(key)) Nenue@87: end Nenue@87: end Nenue@87: until not(i or j) Nenue@87: end Nenue@87: Nenue@66: local profile = D.currentProfile Nenue@66: local setAll Nenue@70: Nenue@70: -- if nothing was found, then do an all toggle Nenue@66: if #search < 1 then Nenue@70: search = self.sigID -- using this since it lists frame ID's Nenue@66: setAll = true Nenue@66: end Nenue@70: Nenue@70: -- sort global enable state Nenue@66: if setAll then Nenue@66: --oldprint('setall', setAll) Nenue@66: profile.enabled = (not profile.enabled) and true or nil Nenue@66: if force == 0 then Nenue@66: profile.enabled = nil Nenue@66: end Nenue@66: end Nenue@66: Nenue@70: -- sort local enable states: if global enable, apply that change to channel Nenue@70: -- else, channel enable takes precedence Nenue@66: for i, id in pairs(search) do Nenue@66: local c = self.console[id] Nenue@66: if setAll then Nenue@70: c.enabled = profile.enabled Nenue@66: else Nenue@66: c.enabled = (not c.enabled) and true or nil Nenue@66: if force == 0 then Nenue@66: c.enabled = nil Nenue@66: end Nenue@66: end Nenue@66: Nenue@70: if c.enabled then Nenue@70: profile.enabled = true Nenue@66: c:Show() Nenue@70: else Nenue@66: c:Hide() Nenue@66: end Nenue@66: c:Save() Nenue@66: end Nenue@66: Nenue@66: if setAll then Nenue@66: if profile.enabled then Nenue@66: self:Print('toggled all consoles ON') Nenue@66: if D.console[profile.current_channel] then Nenue@66: D.console[profile.current_channel]:ToFront() Nenue@66: end Nenue@66: else Nenue@66: self:Print('toggled all consoles OFF') Nenue@66: end Nenue@66: else Nenue@66: local result = {} Nenue@66: for i, id in pairs(search) do Nenue@66: result[i] = tostring(id) .. ' = ' .. (self.console[id].enabled and 'ON' or 'OFF') Nenue@66: end Nenue@66: self:Print('toggled: '..concat(result, ', ')) Nenue@66: end Nenue@66: end