-- NotificationLayer.lua local P = createMenuSheet("NotificationLayer", true, TriBool.True, TriBool.True) P.queueList = {} P.editMode = false P.sampleWindow = nil -- Loads the queues from the NotificationManager and creates the sample window, that is used to measure the width various strings need. function P.onLoad() orxonox.NotificationManager:getInstance():loadQueues() P.sampleWindow = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/NotificationLayer/Root/SampleWindow") end -- Creates a queue in the GUI. function P.createQueue(name, size) local root = winMgr:getWindow("orxonox/NotificationLayer/Root") local queue = winMgr:createWindow("MenuWidgets/Listbox", "orxonox/NotificationLayer/Root/Queue/" .. name) queue:setProperty("BackgroundColor", "00FFFFFF") -- Set background to be fully transparent. root:addChildWindow(queue) queue:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, 0))) queue:setSize(CEGUI.UVector2(CEGUI.UDim(1.0, 0), CEGUI.UDim(0, P.queueHeightHelper(queue, size)))) local queueTuple = { ["window"] = queue, ["name"] = name, ["edit"] = nil, ["visible"] = false } P.queueList[name] = queueTuple -- name access P.setVisible(queueTuple, false) -- Set the queue to invisible as long as there are no notifications in it. end -- Removes a queue from the GUI. function P.removeQueue(queueName) local queue = P.queueList[queueName] if queue ~= nil then winMgr:destroyWindow(queue.window) end P.queueList[queueName] = nil end -- Pushes an input notification to the input queue. function P.pushNotification(queueName, notification) local queue = P.queueList[queueName] if queue == nil then return end item = CEGUI.createListboxTextItem(notification) local listbox = CEGUI.toListbox(queue.window) -- Add the item to the top of the listbox. if listbox:getItemCount() == 0 then listbox:addItem(item) else listbox:insertItem(item, listbox:getListboxItemFromIndex(0)) end -- If the queue has been invisible, set it to visible. if queue.visible == false then P.setVisible(queue, true) end end -- Pops the least recently added notification from the queue. function P.popNotification(queueName) local queue = P.queueList[queueName] if queue == nil then return end local listbox = CEGUI.toListbox(queue.window) -- Removes the item from the bottom of the listbox. listbox:removeItem(listbox:getListboxItemFromIndex(listbox:getItemCount()-1)) -- Sets the queue to invisible if there are no more notifications in it. if listbox:getItemCount() == 0 then P.setVisible(queue, false) end end -- Removes a notification at a given index from the queue. function P.removeNotification(queueName, index) local queue = P.queueList[queueName] if queue == nil then return end local listbox = CEGUI.toListbox(queue.window) -- Removes the item. listbox:removeItem(listbox:getListboxItemFromIndex(tonumber(index))) -- Sets the queue to invisible if there are no more notifications in it. if listbox:getItemCount() == 0 then P.setVisible(queue, false) end end -- Clears the queue. Removes all notifications from it. function P.clearQueue(queueName) local queue = P.queueList[queueName] if queue == nil then return end local listbox = CEGUI.toListbox(queue.window) CEGUI.toListbox(queue.window):resetList() -- Sets the queue to invisible. P.setVisible(queue, false) end -- Sets the visibility of the queue. function P.setVisible(queue, visible) if queue == nil then return end queue.window:setVisible(visible) queue.visible = visible end -- Enter the edit mode of the notification layer. function P.enterEditMode() P.editMode = true local root = winMgr:getWindow("orxonox/NotificationLayer/Root") --Add control frame window. local window = winMgr:createWindow("MenuWidgets/FrameWindow", "orxonox/NotificationLayer/Root/EditMode/ControlWindow") local frame = tolua.cast(window, "CEGUI::FrameWindow") frame:setCloseButtonEnabled(false) frame:setText("NotificationLayer Control Window") frame:setSize(CEGUI.UVector2(CEGUI.UDim(0.7, 0), CEGUI.UDim(0.2, 0))) root:addChildWindow(window) local pane = winMgr:createWindow("MenuWidgets/ScrollablePane", "orxonox/NotificationLayer/Root/EditMode/ControlWindow/ScrollingPane") pane:setSize(CEGUI.UVector2(CEGUI.UDim(1,-20), CEGUI.UDim(1,-30))) pane:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 10), CEGUI.UDim(0, 26))) window:addChildWindow(pane) vertOffset = 0 horzOffset = 0 -- Line to be able to create a new queue. local newQueueTitle = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/NotificationLayer/Root/EditMode/ControlWindow/NewQueueTitle") newQueueTitle:setText("Create a new NotificationQueue:") local size = getMinTextSize(newQueueTitle) local textHeight = size[1] newQueueTitle:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]), CEGUI.UDim(0, textHeight))) newQueueTitle:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset))) pane:addChildWindow(newQueueTitle) horzOffset = horzOffset + size[2] + 5 local newQueueName = winMgr:createWindow("MenuWidgets/Editbox", "orxonox/NotificationLayer/Root/EditMode/ControlWindow/NewQueueName") newQueueName:setProperty("ReadOnly", "set:False") newQueueName:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]), CEGUI.UDim(0, textHeight))) newQueueName:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset))) horzOffset = horzOffset + size[2] + 5 pane:addChildWindow(newQueueName) local create = winMgr:createWindow("MenuWidgets/Button", "orxonox/NotificationLayer/Root/EditMode/ControlWindow/CreateNewQueue") create:setText("create") P.sampleWindow:setText("create") size = getMinTextSize(P.sampleWindow) create:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]+20), CEGUI.UDim(0, textHeight))) create:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset))) orxonox.GUIManager:subscribeEventHelper(create, "Clicked", P.name .. ".createNewQueue_clicked") pane:addChildWindow(create) horzOffset = horzOffset + size[2]+20 + 5 vertOffset = vertOffset + textHeight + 5 horzOffset = 0 -- Button to leave the edit mode. local leave = winMgr:createWindow("MenuWidgets/Button", "orxonox/NotificationLayer/Root/EditMode/ControlWindow/LeaveEditModeButton") leave:setText("leave Edit Mode") P.sampleWindow:setText("leave Edit Mode") size = getMinTextSize(P.sampleWindow) leave:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]+20), CEGUI.UDim(0, textHeight))) leave:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset))) orxonox.GUIManager:subscribeEventHelper(leave, "Clicked", P.name .. ".leaveEditMode_clicked") pane:addChildWindow(leave) horzOffset = horzOffset + size[2]+20 + 5 vertOffset = vertOffset + textHeight + 5 --Replace all queues with FrameWindows for k,v in pairs(P.queueList) do if v ~= nil then local queue = P.queueList[k] -- Remove the window that displays the queue from the root window such that it is no longer displayed. root:removeChildWindow(v.window) -- Create the frame window, with options to edit the queue, that is displayed instead of the queue. local window = P.createQueueEditFrame(v.name) window:setArea(v.window:getArea()) -- Set the frame window size and position to the same as the queue. v.edit = window end end end -- Helper function. Creates a frame for the input queue. function P.createQueueEditFrame(queueName) local root = winMgr:getWindow("orxonox/NotificationLayer/Root") window = winMgr:createWindow("MenuWidgets/FrameWindow", "orxonox/NotificationLayer/Root/EditMode/" .. queueName) local frame = tolua.cast(window, "CEGUI::FrameWindow") frame:setCloseButtonEnabled(true) orxonox.GUIManager:subscribeEventHelper(frame, "CloseClicked", P.name .. ".closeQueue_clicked") frame:setText("NotificationQueue \"" .. queueName .. "\"") root:addChildWindow(window) local pane = winMgr:createWindow("MenuWidgets/ScrollablePane", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/ScrollingPane") pane:setSize(CEGUI.UVector2(CEGUI.UDim(1,-20), CEGUI.UDim(1,-30))) pane:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 10), CEGUI.UDim(0, 26))) window:addChildWindow(pane) local horzOffset = 0 local vertOffset = 0 -- The line that lets you edit the targets of the queue. local targetsTitle = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/TargetsTitle") targetsTitle:setText("Targets:") local size = getMinTextSize(targetsTitle) local textHeight = size[1] targetsTitle:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]), CEGUI.UDim(0, textHeight))) targetsTitle:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset))) pane:addChildWindow(targetsTitle) horzOffset = horzOffset + size[2] + 5 local targets = winMgr:createWindow("MenuWidgets/Editbox", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/Targets") targets:setProperty("ReadOnly", "set:False") local targetsText = orxonox.NotificationManager:getInstance():getQueue(queueName):getTargets() targets:setText(targetsText) P.sampleWindow:setText(targetsText) size = getMinTextSize(P.sampleWindow) targets:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]*2+20), CEGUI.UDim(0, textHeight))) targets:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset))) horzOffset = horzOffset + size[2]*2+20 + 5 pane:addChildWindow(targets) local save = winMgr:createWindow("MenuWidgets/Button", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/Targets/Save") save:setText("save") P.sampleWindow:setText("save") size = getMinTextSize(P.sampleWindow) local saveTextWidth = size[2]+20 save:setSize(CEGUI.UVector2(CEGUI.UDim(0, saveTextWidth), CEGUI.UDim(0, textHeight))) save:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset))) orxonox.GUIManager:subscribeEventHelper(save, "Clicked", P.name .. ".saveTargets_clicked") pane:addChildWindow(save) horzOffset = horzOffset + saveTextWidth vertOffset = vertOffset + textHeight + 5 horzOffset = 0 -- The line that lets you edit the size of the queue. local sizeTitle = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/SizeTitle") sizeTitle:setText("Size:") size = getMinTextSize(sizeTitle) sizeTitle:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]), CEGUI.UDim(0, textHeight))) sizeTitle:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset))) pane:addChildWindow(sizeTitle) horzOffset = horzOffset + size[2] + 5 local queueSize = winMgr:createWindow("MenuWidgets/Editbox", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/Size") queueSize:setProperty("ReadOnly", "set:False") local maxSize = orxonox.NotificationManager:getInstance():getQueue(queueName):getMaxSize() queueSize:setText(maxSize) P.sampleWindow:setText(maxSize) size = getMinTextSize(P.sampleWindow) queueSize:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]*2+20), CEGUI.UDim(0, textHeight))) queueSize:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset))) horzOffset = horzOffset + size[2]*2+20 + 5 pane:addChildWindow(queueSize) save = winMgr:createWindow("MenuWidgets/Button", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/Size/Save") save:setText("save") P.sampleWindow:setText("save") size = getMinTextSize(P.sampleWindow) local saveTextWidth = size[2]+20 save:setSize(CEGUI.UVector2(CEGUI.UDim(0, saveTextWidth), CEGUI.UDim(0, textHeight))) save:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset))) orxonox.GUIManager:subscribeEventHelper(save, "Clicked", P.name .. ".saveSize_clicked") pane:addChildWindow(save) horzOffset = horzOffset + saveTextWidth vertOffset = vertOffset + textHeight + 5 horzOffset = 0 -- The line that lets you edit the display time of the queue. local displayTimeTitle = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/DisplayTimeTitle") displayTimeTitle:setText("Display time:") size = getMinTextSize(displayTimeTitle) displayTimeTitle:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]), CEGUI.UDim(0, textHeight))) displayTimeTitle:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset))) pane:addChildWindow(displayTimeTitle) horzOffset = horzOffset + size[2] + 5 local displayTime = winMgr:createWindow("MenuWidgets/Editbox", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/DisplayTime") displayTime:setProperty("ReadOnly", "set:False") local time = orxonox.NotificationManager:getInstance():getQueue(queueName):getDisplayTime() displayTime:setText(time) P.sampleWindow:setText(time) size = getMinTextSize(P.sampleWindow) displayTime:setSize(CEGUI.UVector2(CEGUI.UDim(0, size[2]*2+20), CEGUI.UDim(0, textHeight))) displayTime:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset))) horzOffset = horzOffset + size[2]*2+20 + 5 pane:addChildWindow(displayTime) save = winMgr:createWindow("MenuWidgets/Button", "orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/DisplayTime/Save") save:setText("save") P.sampleWindow:setText("save") size = getMinTextSize(P.sampleWindow) local saveTextWidth = size[2]+20 save:setSize(CEGUI.UVector2(CEGUI.UDim(0, saveTextWidth), CEGUI.UDim(0, textHeight))) save:setPosition(CEGUI.UVector2(CEGUI.UDim(0, horzOffset), CEGUI.UDim(0, vertOffset))) orxonox.GUIManager:subscribeEventHelper(save, "Clicked", P.name .. ".saveDisplayTime_clicked") pane:addChildWindow(save) horzOffset = horzOffset + saveTextWidth vertOffset = vertOffset + textHeight + 5 return window end -- Leave the edit mode. function P.leaveEditMode() P.editMode = false local root = winMgr:getWindow("orxonox/NotificationLayer/Root") --Replace all queues with FrameWindows for k,v in pairs(P.queueList) do if v ~= nil then -- Add the queue window to the root window to have it displayed again. root:addChildWindow(v.window) -- Set the size and position of the queue window to the size and position of the queue edit frame. v.window:setArea(v.edit:getArea()) -- Destroy the edit frame. winMgr:destroyWindow(v.edit) v.edit = nil end end --Remove control window winMgr:destroyWindow(winMgr:getWindow("orxonox/NotificationLayer/Root/EditMode/ControlWindow")) end -- Is called after the sheet has been hidden. function P.onQuit() -- If we leave the edit mode we show the sheet again. if P.editMode then P.leaveEditMode() showMenuSheet(P.name, false, true) end end -- If the button to save the targets of a queue has been clicked. function P. saveTargets_clicked(e) local we = CEGUI.toWindowEventArgs(e) local name = we.window:getName() local match = string.gmatch(name, "EditMode/.*/Targets/Save") local nameStr = match() local queueName = string.sub(nameStr, 10, string.len(nameStr)-13) local window = winMgr:getWindow("orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/Targets") local save = winMgr:getWindow("orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/Targets/Save") local width = window:getWidth():asAbsolute(1) local queue = orxonox.NotificationManager:getInstance():getQueue(queueName) -- Set the new targets. queue:setTargets(window:getText()) local targets = queue:getTargets() window:setText(targets) P.sampleWindow:setText(targets) local size = getMinTextSize(P.sampleWindow) -- Adjust the width of the targets field. window:setWidth(CEGUI.UDim(0, size[2]*2+20)) -- Adjust the position of the save button after the targets field. save:setXPosition(CEGUI.UDim(0, save:getXPosition():asAbsolute(1)-width+window:getWidth():asAbsolute(1))) end -- If the button to save the size if a queue has been clicked. function P. saveSize_clicked(e) local we = CEGUI.toWindowEventArgs(e) local name = we.window:getName() local match = string.gmatch(name, "EditMode/.*/Size/Save") local nameStr = match() local queueName = string.sub(nameStr, 10, string.len(nameStr)-10) local window = winMgr:getWindow("orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/Size") local save = winMgr:getWindow("orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/Size/Save") local width = window:getWidth():asAbsolute(1) local queue = orxonox.NotificationManager:getInstance():getQueue(queueName) -- Set the new size. queue:setMaxSize(tonumber(window:getText())) local maxSize = queue:getMaxSize() window:setText(maxSize) P.sampleWindow:setText(maxSize) local size = getMinTextSize(P.sampleWindow) -- Adjust the width of the size field. window:setWidth(CEGUI.UDim(0, size[2]*2+20)) -- Adjust the position of the save button after the size field. save:setXPosition(CEGUI.UDim(0, save:getXPosition():asAbsolute(1)-width+window:getWidth():asAbsolute(1))) end -- If the button to save the display time if a queue has been clicked. function P. saveDisplayTime_clicked(e) local we = CEGUI.toWindowEventArgs(e) local name = we.window:getName() local match = string.gmatch(name, "EditMode/.*/DisplayTime/Save") local nameStr = match() local queueName = string.sub(nameStr, 10, string.len(nameStr)-17) local window = winMgr:getWindow("orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/DisplayTime") local save = winMgr:getWindow("orxonox/NotificationLayer/Root/EditMode/" .. queueName .. "/DisplayTime/Save") local width = window:getWidth():asAbsolute(1) local queue = orxonox.NotificationManager:getInstance():getQueue(queueName) -- Set the new display time. queue:setDisplayTime(tonumber(window:getText())) local time = queue:getDisplayTime() window:setText(time) P.sampleWindow:setText(time) local size = getMinTextSize(P.sampleWindow) -- Adjust the width of the display time field. window:setWidth(CEGUI.UDim(0, size[2]*2+20)) -- Adjust the position of the save button after the display time field. save:setXPosition(CEGUI.UDim(0, save:getXPosition():asAbsolute(1)-width+window:getWidth():asAbsolute(1))) end -- if the button to create a new queue has been clicked. function P.createNewQueue_clicked(e) local window = winMgr:getWindow("orxonox/NotificationLayer/Root/EditMode/ControlWindow/NewQueueName") local name = window:getText() local queue = P.queueList[name] -- Test if a queue with that name already exists. if queue ~= nil then window:setText("Queue with that name already exists.") return end -- Creates the new queue. orxonox.NotificationManager:getInstance():createQueue(name) queue = P.queueList[name] if queue == nil then return end -- Create the frame that represents the queue in edit mode, since that's what we're in. local frame = P.createQueueEditFrame(name) local root = winMgr:getWindow("orxonox/NotificationLayer/Root") -- Remove the queue window from the root window, since we're in edit mode. root:removeChildWindow(queue.window) -- Set the frame window size and position to that of the queue window. frame:setArea(queue.window:getArea()) queue.edit = frame -- Reset the text to create a new queue. window:setText("") end -- If the button to leave the edit mode has been clicked. function P.leaveEditMode_clicked(e) hideMenuSheet(P.name) end -- If the button to close the queue has been clicked. function P.closeQueue_clicked(e) local we = CEGUI.toWindowEventArgs(e) local name = we.window:getName() local match = string.gmatch(name, "EditMode/.*") local nameStr = match() local queueName = string.sub(nameStr, 10, string.len(nameStr)) -- Destroy the frame window, winMgr:destroyWindow(P.queueList[queueName].edit) P.queueList[queueName].edit = nil -- Destroy the queue. orxonox.NotificationManager:getInstance():getQueue(queueName):destroy() end -- Helper function. Returns height a queue needs to have to display 'size' items. function P.queueHeightHelper(queue, size) local listbox = CEGUI.toListbox(queue) local item = CEGUI.createListboxTextItem("Text") listbox:addItem(item) local singleItemHeight = listbox:getTotalItemsHeight() local lookAndFeel = CEGUI.WidgetLookManager:getSingleton():getWidgetLook(queue:getLookNFeel()) local formattedArea = lookAndFeel:getNamedArea("ItemRenderingArea"):getArea():getPixelRect(queue) local frameHeight = queue:getUnclippedPixelRect():getHeight() - formattedArea:getHeight() listbox:removeItem(item) return frameHeight + singleItemHeight*size end return P