diff --git a/openlp/core/display/html/display.css b/openlp/core/display/html/display.css new file mode 100644 index 000000000..e68b1ac28 --- /dev/null +++ b/openlp/core/display/html/display.css @@ -0,0 +1,57 @@ +/* Animation key frames for horizontal scrolling of alert */ +@keyframes alert-scrolling-text { + from { margin-left: 100%; } + to { margin-left: -300% } +} + +.horizontal-scroll-animation { + animation-duration: 10s; + animation-iteration-count: 1; + animation-timing-function: linear; + animation-name: alert-scrolling-text; +} + +/* ALERT STYLING */ + +.normal { + position: absolute; + margin: 0; + padding: 0; + left: 0; + z-index: 10; + width: 100%; + height: 0%; + vertical-align: middle; + overflow: hidden; + visibility:hidden; +} + +.normal.middle { + top: 50%; + left: 50%; + margin-right: -50%; + transform: translate(-50%, -50%); + bottom: initial; +} + +.normal.top { + top: 0; + bottom: initial; +} + +.normal.bottom { + top: initial; + bottom: 0; +} + +#alert { + position: relative; + top: 50%; + transform: translateY(-50%); + margin: 0% 0% 0% 100%; + z-index: 11; + overflow: visible; + white-space: nowrap; + color: #ffffff; + visibility: hidden; +} \ No newline at end of file diff --git a/openlp/core/display/html/display.html b/openlp/core/display/html/display.html index d6c9fffec..014138202 100644 --- a/openlp/core/display/html/display.html +++ b/openlp/core/display/html/display.html @@ -3,6 +3,7 @@ Display Window + - +
-

Testing alerts

+

Testing alerts

+ diff --git a/openlp/core/display/html/display.js b/openlp/core/display/html/display.js index 9250f0312..9a0b2ded3 100644 --- a/openlp/core/display/html/display.js +++ b/openlp/core/display/html/display.js @@ -67,17 +67,15 @@ var TransitionState = { */ var AnimationState = { NoAnimation: "noAnimation", - ScrollingAnimation: "scrollingAnimation", - FadeInAnimation: "fadeInAnimation", - FadeOutAnimation: "fadeOutAnimation" + ScrollingAnimation: "scrollingAnimation" }; /** * Alert location enumeration */ var AlertLocation = { - Top: "0", - Middle: "1", - Bottom: "2" + Top: 0, + Middle: 1, + Bottom: 2 }; /** @@ -411,119 +409,97 @@ var Display = { * @param {string} text - The alert text * @param {int} location - The location of the text (top, middle or bottom) */ - alert: function (text, location) { - console.debug(" alert text: " + text + ", location: " + location); + alert: function (text, alert_settings) { + console.debug(" alert text: " + text + ", alert settings: " + alert_settings); if (text == "") { return null; } + var settings = JSON.parse(alert_settings); + var alertBackground = $("#alert-background")[0]; var alertText = $("#alert")[0]; + + alertText.innerHTML = text; - alertText.innerHTML = text; - - /* Bring in the transition background */ - Display._transitionState = Display.doEntranceTransition(location); - + /* Start the entrance transition */ + Display._transitionState = Display.doEntranceTransition(settings); + // TODO: Add functinoality for no scroll and queue if not all alerts have been displayed alertBackground.addEventListener('transitionend', function (e) { e.stopPropagation(); - if (Display._transitionState == TransitionState.EntranceTransition) { + if (Display._transitionState === TransitionState.EntranceTransition) { alertText.style.visibility = "visible"; alertText.classList.add("horizontal-scroll-animation"); + Display._animationState = AnimationState.ScrollingAnimation; + Display._transitionState = TransitionState.NoTransition } - else if (Display._transitionState == TransitionState.ExitTransition) { + else if (Display._transitionState === TransitionState.ExitTransition) { Display._transitionState = TransitionState.NoTransition; - alertBackground.style.visibility = "hidden"; alertText.style.visibility = "hidden"; - alertBackground.style.top = ""; - alertBackground.style.bottom = ""; - alertBackground.style.height = ""; - alertBackground.style.transition = ""; - alertBackground.classList.remove("middle-exit-animation"); + alertBackground.classList = ""; + alertBackground.classList.add("normal"); } }); - alertBackground.addEventListener('animationend', function () { - - if (Display._animationState == AnimationState.FadeInAnimation) { - alertText.style.visibility = "visible"; - alertText.classList.add("horizontal-scroll-animation"); - alertText.classList.remove("middle-entrance-animation"); - Display._animationState = AnimationState.ScrollingAnimation; - } - else if (Display._animationState == AnimationState.FadeOutAnimation) { - alertBackground.style.visibility = "hidden"; - alertBackground.classList.remove("middle-exit-animation"); - Display._animationState = AnimationState.NoAnimation; - } - else if (alertText.classList.contains("horizontal-scroll-animation")) { + alertBackground.addEventListener('animationend', function (e) { + e.stopPropagation(); + if (Display._animationState === AnimationState.ScrollingAnimation) { alertText.classList.remove("horizontal-scroll-animation"); alertText.style.visibility = "hidden"; Display._animationState = AnimationState.NoAnimation; - Display._transitionState = Display.doExitTransition(location); + Display._transitionState = Display.doExitTransition(); } - }); /* * The implementation should show an alert. * It should be able to handle receiving a new alert before a previous one is "finished", basically queueing it. */ - return location; + return settings.location; }, /** * Start background entrance transition for display of alert - * @param {string} location - String showing the location of the alert on screen + * @param {number} location - Number showing the location of the alert on screen */ - doEntranceTransition: function (location) { + doEntranceTransition: function (settings) { var alertBackground = $("#alert-background")[0]; - - switch (location) { + var alertText = $("#alert")[0]; + switch (settings.location) { case AlertLocation.Top: - alertBackground.style.bottom = ''; - alertBackground.style.top = '0px'; - alertBackground.style.height = "25%"; - alertBackground.style.transition = "2s linear"; + alertBackground.classList.add("top"); break; case AlertLocation.Middle: - alertBackground.style.top = ((window.innerHeight - alertBackground.clientHeight) / 2) + 'px'; - alertBackground.style.height = "25%"; - alertBackground.classList.add("middle-entrance-animation"); - Display._animationState = AnimationState.FadeInAnimation; + // alertBackground.style.top = ((window.innerHeight - alertBackground.clientHeight) / 2) + 'px'; + alertBackground.classList.add("middle"); break; case AlertLocation.Bottom: default: - alertBackground.style.top = ''; - alertBackground.style.bottom = '0px'; - alertBackground.style.height = "25%"; - alertBackground.style.transition= "2s linear"; + alertBackground.classList.add("bottom"); break; } - alertBackground.style.visibility = "visible"; + alertText.style.color = settings.font_color; + alertText.style.fontFamily = settings.font_face; + alertText.style.fontSize = settings.font_size + "pt"; + alertBackground.style.backgroundColor = settings.background_color; + // Wait for styles to be set first before starting transitions + setTimeout( function() { + alertBackground.style.height = "25%"; + alertBackground.style.transition = "2s linear"; + alertBackground.style.visibility = "visible"; + }, 200); return TransitionState.EntranceTransition; - }, /** * Start background exit transition once alert has been displayed * @param {string} location - Integer showing the location of the alert on screen */ - doExitTransition: function (location) { - + doExitTransition: function () { var alertBackground = $("#alert-background")[0]; - - if (location == AlertLocation.Top || location == AlertLocation.Bottom) { - alertBackground.style.height = "0%"; - alertBackground.style.transition = '2s linear'; - } - else if (location == AlertLocation.Middle) { - alertBackground.classList.add("middle-exit-animation"); - alertBackground.style.height = "0%"; - Display._animationState = AnimationState.FadeOutAnimation; - } - + alertBackground.style.height = "0%"; + alertBackground.style.transition = '2s linear'; return TransitionState.ExitTransition; }, /** diff --git a/openlp/core/display/window.py b/openlp/core/display/window.py index 30284483c..e1b67f34e 100644 --- a/openlp/core/display/window.py +++ b/openlp/core/display/window.py @@ -397,8 +397,9 @@ class DisplayWindow(QtWidgets.QWidget): self.scale = scale self.run_javascript('Display.setScale({scale});'.format(scale=scale * 100)) - def alert(self, text, location): + def alert(self, text, settings): """ Set an alert """ - self.run_javascript('Display.alert("{text}", "{location}");'.format(text=text, location=location)) + self.run_javascript('Display.alert("{text}", \'{settings}\');'.format(text=text, settings=settings)) + # TODO: Add option scrolling option \ No newline at end of file diff --git a/openlp/plugins/alerts/lib/alertsmanager.py b/openlp/plugins/alerts/lib/alertsmanager.py index 0fca8bdd6..6d2a221d0 100644 --- a/openlp/plugins/alerts/lib/alertsmanager.py +++ b/openlp/plugins/alerts/lib/alertsmanager.py @@ -23,6 +23,8 @@ The :mod:`~openlp.plugins.alerts.lib.alertsmanager` module contains the part of the plugin which manages storing and displaying of alerts. """ +import json + from PyQt5 import QtCore from openlp.core.common.i18n import translate @@ -83,8 +85,16 @@ class AlertsManager(QtCore.QObject, RegistryBase, LogMixin, RegistryProperties): not Settings().value('core/display on monitor')): return text = self.alert_list.pop(0) - alert_tab = self.parent().settings_tab - self.live_controller.displays[0].alert(text, alert_tab.location) + # Put alert settings together for dict + alert_settings = { + 'background_color': Settings().value('alerts/background color'), + 'location': Settings().value('alerts/location'), + 'font_face': Settings().value('alerts/font face'), + 'font_size': Settings().value('alerts/font size'), + 'font_color': Settings().value('alerts/font color'), + 'timeout': Settings().value().value('alerts/timeout') + } + self.live_controller.displays[0].alert(text, json.dumps(alert_settings)) # Check to see if we have a timer running. #if self.timer_id == 0: # self.timer_id = self.startTimer(int(alert_tab.timeout) * 1000) diff --git a/tests/js/test_display.js b/tests/js/test_display.js index a83eef643..36d5eae68 100644 --- a/tests/js/test_display.js +++ b/tests/js/test_display.js @@ -154,7 +154,7 @@ describe("The Display object", function () { }); describe("Display.alert", function () { - var alertBackground, alert; + var alertBackground, alert, settings; beforeEach(function () { document.body.innerHTML = ""; @@ -164,60 +164,91 @@ describe("Display.alert", function () { alert = document.createElement("p"); alert.setAttribute("id","alert"); alertBackground.appendChild(alert); + settings = '{ \ + "location": 1, "font_face": "Segoe UI, Tahoma, Geneva, Verdana, sans-serif", \ + "font_size": 40, "font_color": "#ffffff", "background_color": "#660000" \ + }'; }); it("should return null if called without any text", function () { - expect(Display.alert("","2")).toBeNull(); + expect(Display.alert("",settings)).toBeNull(); }); - it("should set correct alert text", function () { - Display.alert("OPEN-LP-3.0 Alert Test", "2"); + it("should set the correct alert text", function () { + Display.alert("OPEN-LP-3.0 Alert Test", settings); expect(alert.innerHTML).toEqual("OPEN-LP-3.0 Alert Test"); }); it("should set the correct alert position", function () { - expect(Display.alert("Alert Location Test","2")).toEqual("2"); + expect(Display.alert("Alert Location Test", settings)).toEqual(1); }); }); describe("The doEntranceTransition", function () { - var alertBackground; + var alertBackground, alertText; + // TODO: Fix tests to accommodate new behaviour with CSS classes and settings modification beforeEach(function() { document.body.innerHTML = ""; alertBackground = document.createElement("div"); alertBackground.setAttribute("id", "alert-background"); document.body.appendChild(alertBackground); + alertText = document.createElement("p"); + alertText.setAttribute("id","alert"); + alertBackground.appendChild(alertText); alertBackground.style.top = '0px'; - alertBackground.style.height = "0%"; + alertBackground.style.height = "0%"; }); it("should set the correct styles for the alert when location is top of the page", function () { - Display.doEntranceTransition("0"); - expect(alertBackground.style.bottom).toEqual(''); - expect(alertBackground.style.top).toEqual('0px'); - expect(alertBackground.style.transition).toEqual("2s linear"); - expect(alertBackground.style.height).toEqual("25%"); - expect(alertBackground.style.visibility).toEqual("visible"); + var settings = { + "location": 0, "font_face": "Segoe UI, Tahoma, Geneva, Verdana, sans-serif", + "font_size": 40, "font_color": "#ffffff", "background_color": "#660000" + }; + + Display.doEntranceTransition(settings); + + setTimeout( function() { + expect(alertBackground.style.bottom).toEqual(''); + expect(alertBackground.style.top).toEqual('0px'); + expect(alertBackground.style.transition).toEqual("2s linear"); + expect(alertBackground.style.height).toEqual("25%"); + expect(alertBackground.style.visibility).toEqual("visible"); + }, 500); + }); it("should set the correct styles for the alert when location is middle of the page", function () { - Display.doEntranceTransition("1"); + var settings = { + "location": 0, "font_face": "Segoe UI, Tahoma, Geneva, Verdana, sans-serif", + "font_size": 40, "font_color": "#ffffff", "background_color": "#660000" + }; + + Display.doEntranceTransition(settings); + //To be replaced var middlePosition = ((window.innerHeight - alertBackground.clientHeight) / 2) + 'px'; expect(alertBackground.style.top).toEqual(middlePosition); - expect(alertBackground.classList.contains("middle-entrance-animation")); expect(alertBackground.style.height).toEqual("25%"); expect(alertBackground.style.visibility).toEqual("visible"); }); it("should set the correct styles for the alert when location is bottom of the page", function () { - Display.doEntranceTransition("2"); - expect(alertBackground.style.top).toEqual(''); - expect(alertBackground.style.bottom).toEqual('0px'); - expect(alertBackground.style.transition).toEqual("2s linear"); - expect(alertBackground.style.height).toEqual("25%"); - expect(alertBackground.style.visibility).toEqual("visible"); + var settings = { + "location": 0, "font_face": "Segoe UI, Tahoma, Geneva, Verdana, sans-serif", + "font_size": 40, "font_color": "#ffffff", "background_color": "#660000" + }; + + Display.doEntranceTransition(settings); + + setTimeout(function() { + expect(alertBackground.style.top).toEqual(''); + expect(alertBackground.style.bottom).toEqual('0px'); + expect(alertBackground.style.transition).toEqual("2s linear"); + expect(alertBackground.style.height).toEqual("25%"); + expect(alertBackground.style.visibility).toEqual("visible"); + }, 500); + }); }); @@ -232,19 +263,22 @@ describe("The doExitTransition", function () { }); it("should remove the styles correctly when the location is the top of the page", function () { - Display.doExitTransition("0"); + Display.doExitTransition(0); + expect(alertBackground.style.height).toEqual('0%'); expect(alertBackground.style.transition).toEqual("2s linear"); }); it("should remove the styles correctly when the location is middle of the page", function () { - Display.doExitTransition("1"); + Display.doExitTransition(1); + expect(alertBackground.style.height).toEqual('0%'); expect(alertBackground.classList.contains("middle-exit-animation")); }); it("should remove the styles correctly when the location is the bottom of the page", function () { - Display.doExitTransition("2"); + Display.doExitTransition(2); + expect(alertBackground.style.height).toEqual('0%'); expect(alertBackground.style.transition).toEqual("2s linear"); });