Don't reload images on start (they are already loaded)

Someone should check if the start param in this function is even needed now, looks like an artifact from the old renderer
This commit is contained in:
Daniel 2020-03-05 20:35:25 +00:00 committed by Tim Bentley
parent 79950b6a85
commit d5892b6258
13 changed files with 543 additions and 270 deletions

View File

@ -333,6 +333,7 @@ class Settings(QtCore.QSettings):
'themes/last directory import': None,
'themes/theme level': ThemeLevel.Global,
'themes/wrap footer': False,
'themes/item transitions': False,
'user interface/live panel': True,
'user interface/live splitter geometry': QtCore.QByteArray(),
'user interface/lock panel': True,

View File

@ -22,14 +22,53 @@ sup {
font-size: smaller !important;
}
body,
.reveal .slides,
.reveal .footer {
transition: none;
z-index: 2;
}
body.transition,
body.transition .reveal .slides,
body.transition .reveal .footer {
/* Transition speed for content visibility */
transition: opacity 800ms ease-in-out !important;
}
.reveal .slide-background {
opacity: 1;
visibility: visible;
transition: none !important;
z-index: 2;
/* important required to override inline attributes */
background-repeat: no-repeat !important;
background-size: cover !important;
background-position: 50% 50% !important;
}
.reveal .slide-background:nth-child(n+3) {
/* Hide backgrounds beyond the first 2 (prevents ugly transitions in corner case) */
visibility: hidden;
}
.reveal .slide-background.future,
.reveal .slide-background.past {
opacity: 0;
}
body.transition .reveal .slide-background {
transition: all 800ms ease-in-out !important;
}
.reveal .slides > section,
.reveal .slides > section > section {
padding: 0;
max-height: 100%;
}
.reveal .slides > section.text-slides {
/* Need to override reveal styles to use our text aligment */
.reveal .slides > section {
/* Need to override reveal styles to use our text alignment */
display: flex !important;
flex-direction: column;
word-wrap: break-word;
@ -318,21 +357,24 @@ sup {
.reveal[class*=fade] .slides section.present:not([data-transition]) {
transition-delay: 400ms; }
.reveal .slides section.present[data-transition*=fade],
.reveal .slides section.present[data-transition-speed="fast"][data-transition*=fade],
.reveal[data-transition-speed="fast"][class*=fade] .slides section.present:not([data-transition]) {
transition-delay: 200ms; }
.reveal .slides section.present[data-transition*=fade],
.reveal .slides section.present[data-transition-speed="slow"][data-transition*=fade],
.reveal[data-transition-speed="slow"][class*=fade] .slides section.present:not([data-transition]) {
transition-delay: 800ms; }
.reveal[class*=fade] .slides section {
.reveal[class*=fade] .slides section,
.reveal .slides section[class*=fade] {
transition-duration: 400ms !important; }
.reveal[data-transition-speed="fast"][class*=fade] .slides section {
.reveal[data-transition-speed="fast"][class*=fade] .slides section,
.reveal .slides section[data-transition-speed="fast"][class*=fade] {
transition-duration: 200ms !important; }
.reveal[data-transition-speed="slow"][class*=fade] .slides section {
.reveal[data-transition-speed="slow"][class*=fade] .slides section,
.reveal .slides section[data-transition-speed="slow"][class*=fade] {
transition-duration: 800ms !important; }
.reveal[class*=fade].overview .slides section {

View File

@ -352,6 +352,9 @@ AudioPlayer.prototype.stop = function () {
* The Display object is what we use from OpenLP
*/
var Display = {
_slidesContainer: null,
_footerContainer: null,
_backgroundsContainer: null,
_alerts: [],
_slides: {},
_alertSettings: {},
@ -359,6 +362,8 @@ var Display = {
_transitionState: TransitionState.NoTransition,
_animationState: AnimationState.NoAnimation,
_doTransitions: false,
_doItemTransitions: false,
_themeApplied: true,
_revealConfig: {
margin: 0.0,
minScale: 1.0,
@ -380,9 +385,16 @@ var Display = {
/**
* Start up reveal and do any other initialisation
*/
init: function (doTransitions=false) {
init: function (doTransitions=false, doItemtransitions=false) {
var globalBackground = $("#global-background")[0];
globalBackground.style.cssText = "";
globalBackground.style.setProperty("background", "black");
Display._slidesContainer = $(".slides")[0];
Display._footerContainer = $(".footer")[0];
Display._backgroundsContainer = $(".backgrounds")[0];
Display._doTransitions = doTransitions;
Reveal.initialize(Display._revealConfig);
Display.setItemTransition(doItemtransitions && doTransitions);
displayWatcher.setInitialised(true);
},
/**
@ -394,30 +406,79 @@ var Display = {
Reveal.slide(0);
},
/**
* Set the transition type
* @param {string} transitionType - Can be one of "none", "fade", "slide", "convex", "concave", "zoom"
* @param {string} transitionSpeed - Can be one of "default", "fast", "slow"
* Enable/Disable item transitions
*/
setTransition: function (transitionType, transitionSpeed) {
Reveal.configure({"transition": transitionType, "transitionSpeed": transitionSpeed});
setItemTransition: function (enable) {
Display._doItemTransitions = enable;
var body = $("body")[0];
if (enable) {
body.classList.add("transition");
Reveal.configure({"backgroundTransition": "fade", "transitionSpeed": "default"});
} else {
body.classList.remove("transition");
Reveal.configure({"backgroundTransition": "none"});
}
},
/**
* Clear the current list of slides
*/
clearSlides: function () {
$(".slides")[0].innerHTML = "";
Display._slidesContainer.innerHTML = "";
Display._clearSlidesList();
},
/**
* Clear the current list of slides
*/
_clearSlidesList: function () {
Display._footerContainer.innerHTML = "";
Display._slides = {};
},
/**
* Add new item/slides, replacing the old one
* Clears current list of slides but allows time for a transition animation
* Items are ordered newest to oldest in the slides container
* @param {element} new_slides - New slides to display
* @param {element} is_text - Used to decide if the theme main area constraints should apply
*/
replaceSlides: function (new_slides, is_text=false) {
if (Display._doItemTransitions) {
new_slides.setAttribute('data-transition', "fade");
new_slides.setAttribute('data-transition-speed', "default");
}
new_slides.classList.add("future");
Display.applyTheme(new_slides, is_text);
Display._slidesContainer.prepend(new_slides);
var currentSlide = Reveal.getIndices();
if (Display._doItemTransitions && Display._slidesContainer.children.length >= 2) {
// Set the slide one section ahead so we'll stay on the old slide after reinit
Reveal.slide(1, currentSlide.v);
Display.reinit();
// Timeout to allow time to transition before deleting the old slides
setTimeout (Display._removeLastSection, 5000);
} else {
Reveal.slide(0, currentSlide.v);
Reveal.sync();
Display._removeLastSection();
}
},
/**
* Removes the last slides item if there are more than one
*/
_removeLastSection: function () {
if (Display._slidesContainer.children.length > 1) {
Display._slidesContainer.lastChild.remove();
}
},
/**
* Checks if the present slide content fits within the slide
*/
doesContentFit: function () {
var currSlide = $("section.text-slides");
if (currSlide.length === 0) {
currSlide = $(".slides");
currSlide = Display._footerContainer;
} else {
currSlide = currSlide[0];
}
currSlide = currSlide[0];
console.debug("scrollHeight: " + currSlide.scrollHeight + ", clientHeight: " + currSlide.clientHeight);
return currSlide.clientHeight >= currSlide.scrollHeight;
},
/**
@ -426,22 +487,17 @@ var Display = {
* @param {string} image - Path to the splash image
*/
setStartupSplashScreen: function(bg_color, image) {
Display.clearSlides();
var globalBackground = $("#global-background")[0];
globalBackground.style.cssText = "";
globalBackground.style.setProperty("background", bg_color);
var slidesDiv = $(".slides")[0];
Display._clearSlidesList();
var section = document.createElement("section");
section.setAttribute("id", 0);
section.setAttribute("data-background", bg_color);
section.setAttribute("style", "height: 100%; width: 100%; position: relative;");
section.setAttribute("style", "height: 100%; width: 100%;");
var img = document.createElement('img');
img.src = image;
img.setAttribute("style", "position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; max-height: 100%; max-width: 100%");
section.appendChild(img);
slidesDiv.appendChild(section);
Display._slides['0'] = 0;
Display.reinit();
Display.replaceSlides(section);
},
/**
* Set fullscreen image from path
@ -450,10 +506,6 @@ var Display = {
*/
setFullscreenImage: function(bg_color, image) {
Display.clearSlides();
var globalBackground = $("#global-background")[0];
globalBackground.style.cssText = "";
globalBackground.style.setProperty("background", bg_color);
var slidesDiv = $(".slides")[0];
var section = document.createElement("section");
section.setAttribute("id", 0);
section.setAttribute("data-background", bg_color);
@ -462,9 +514,8 @@ var Display = {
img.src = image;
img.setAttribute("style", "height: 100%; width: 100%");
section.appendChild(img);
slidesDiv.appendChild(section);
Display._slides['0'] = 0;
Display.reinit();
Display.replaceSlides(parentSection);
},
/**
* Set fullscreen image from base64 data
@ -473,10 +524,6 @@ var Display = {
*/
setFullscreenImageFromData: function(bg_color, image_data) {
Display.clearSlides();
var globalBackground = $("#global-background")[0];
globalBackground.style.cssText = "";
globalBackground.style.setProperty("background", bg_color);
var slidesDiv = $(".slides")[0];
var section = document.createElement("section");
section.setAttribute("id", 0);
section.setAttribute("data-background", bg_color);
@ -485,7 +532,7 @@ var Display = {
img.src = 'data:image/png;base64,' + image_data;
img.setAttribute("style", "height: 100%; width: 100%");
section.appendChild(img);
slidesDiv.appendChild(section);
Display._slidesContainer.appendChild(section);
Display._slides['0'] = 0;
Display.reinit();
},
@ -632,62 +679,64 @@ var Display = {
}
},
/**
* Add a slide. If the slide exists but the HTML is different, update the slide.
* Create a text slide.
* @param {string} verse - The verse number, e.g. "v1"
* @param {string} text - The HTML for the verse, e.g. "line1<br>line2"
* @param {string} footer_text - The HTML for the footer
* @param {bool} reinit - True if React should reinit when creating a new slide
*/
addTextSlide: function (verse, text, footerText, reinit=true) {
_createTextSlide: function (verse, text) {
var slide;
var html = _prepareText(text);
if (Display._slides.hasOwnProperty(verse)) {
slide = $("#" + verse)[0];
if (slide.innerHTML != html) {
slide.innerHTML = html;
}
} else {
var parent = $("section.text-slides");
if (parent.length === 0) {
Display._createTextContainer();
parent = $("section.text-slides");
}
parent = parent[0];
slide = document.createElement("section");
slide.setAttribute("id", verse);
slide.innerHTML = html;
parent.appendChild(slide);
Display._slides[verse] = parent.children.length - 1;
if (footerText) {
$(".footer")[0].innerHTML = footerText;
}
if (reinit) {
Display.reinit();
}
}
slide = document.createElement("section");
slide.setAttribute("id", verse);
slide.innerHTML = html;
return slide;
},
/**
* Set text slides.
* @param {Object[]} slides - A list of slides to add as JS objects: {"verse": "v1", "text": "line 1\nline2"}
*/
setTextSlides: function (slides) {
Display.clearSlides();
Display._clearSlidesList();
var slide_html;
var parentSection = document.createElement("section");
parentSection.classList = "text-slides";
slides.forEach(function (slide) {
Display.addTextSlide(slide.verse, slide.text, slide.footer, false);
slide_html = Display._createTextSlide(slide.verse, slide.text);
parentSection.appendChild(slide_html);
Display._slides[slide.verse] = parentSection.children.length - 1;
if (slide.footer) {
Display._footerContainer.innerHTML = slide.footer;
}
});
Display.reinit();
Display.replaceSlides(parentSection, true);
},
/**
* Create the <section> that will contain text slides (vertical slides in react)
* Set a single text slide. This changes the slide with no transition.
* Prevents the need to reapply the theme if only changing content.
* @param String slide - Text to put on the slide
*/
_createTextContainer: function () {
var slideContainer = document.createElement("section");
slideContainer.classList = "text-slides";
var slidesDiv = $(".slides")[0];
slidesDiv.appendChild(slideContainer);
// Apply the current theme to the new container
if (!!Display._theme) {
Display.setTheme(Display._theme);
setTextSlide: function (text) {
if (Display._slides.hasOwnProperty("test-slide") && Object.keys(Display._slides).length === 1) {
var slide = $("#" + "test-slide")[0];
var html = _prepareText(text);
if (slide.innerHTML != html) {
slide.innerHTML = html;
}
if (!Display._themeApplied) {
Display.applyTheme(slide.parent);
}
} else {
Display._clearSlidesList();
var slide_html;
var parentSection = document.createElement("section");
parentSection.classList = "text-slides";
slide_html = Display._createTextSlide("test-slide", text);
parentSection.appendChild(slide_html);
Display._slides["test-slide"] = 0;
Display.applyTheme(parentSection);
Display._slidesContainer.innerHTML = "";
Display._slidesContainer.prepend(parentSection);
Display.reinit();
}
},
/**
@ -695,8 +744,7 @@ var Display = {
* @param {Object[]} slides - A list of images to add as JS objects [{"path": "url/to/file"}]
*/
setImageSlides: function (slides) {
Display.clearSlides();
var slidesDiv = $(".slides")[0];
Display._clearSlidesList();
var parentSection = document.createElement("section");
slides.forEach(function (slide, index) {
var section = document.createElement("section");
@ -710,15 +758,14 @@ var Display = {
parentSection.appendChild(section);
Display._slides[index.toString()] = index;
});
slidesDiv.appendChild(parentSection);
Display.reinit();
Display.replaceSlides(parentSection);
},
/**
* Set a video
* @param {Object} video - The video to show as a JS object: {"path": "url/to/file"}
*/
setVideo: function (video) {
Display.clearSlides();
Display._clearSlidesList();
var section = document.createElement("section");
section.setAttribute("data-background", "#000");
var videoElement = document.createElement("video");
@ -747,8 +794,7 @@ var Display = {
mediaWatcher.has_muted(event.target.muted);
});
section.appendChild(videoElement);
$(".slides")[0].appendChild(section);
Display.reinit();
Display.replaceSlides(section);
},
/**
* Play a video
@ -856,32 +902,45 @@ var Display = {
/**
* Blank the screen
*/
blankToBlack: function () {
toBlack: function () {
var documentBody = $("body")[0];
documentBody.style.opacity = 1;
if (!Reveal.isPaused()) {
Reveal.togglePause();
}
// var slidesDiv = $(".slides")[0];
},
/**
* Blank to theme
* Hide all but theme background
*/
blankToTheme: function () {
var slidesDiv = $(".slides")[0];
slidesDiv.style.visibility = "hidden";
var footerDiv = $(".footer")[0];
footerDiv.style.visibility = "hidden";
toTheme: function () {
var documentBody = $("body")[0];
documentBody.style.opacity = 1;
Display._slidesContainer.style.opacity = 0;
Display._footerContainer.style.opacity = 0;
if (Reveal.isPaused()) {
Reveal.togglePause();
}
},
/**
* Hide everything (CAUTION: Causes a invisible mouse barrier)
*/
toTransparent: function () {
Display._slidesContainer.style.opacity = 0;
Display._footerContainer.style.opacity = 0;
var documentBody = $("body")[0];
documentBody.style.opacity = 0;
if (!Reveal.isPaused()) {
Reveal.togglePause();
}
},
/**
* Show the screen
*/
show: function () {
var slidesDiv = $(".slides")[0];
slidesDiv.style.visibility = "visible";
var footerDiv = $(".footer")[0];
footerDiv.style.visibility = "visible";
var documentBody = $("body")[0];
documentBody.style.opacity = 1;
Display._slidesContainer.style.opacity = 1;
Display._footerContainer.style.opacity = 1;
if (Reveal.isPaused()) {
Reveal.togglePause();
}
@ -903,13 +962,31 @@ var Display = {
var dh = parseFloat(_getStyle(d, "height"));
return Math.floor(dh / lh);
},
/**
* Prepare the theme for the next item to be added
* @param theme The theme to be used
*/
setTheme: function (theme) {
Display._theme = theme;
if (Display._theme != theme) {
Display._themeApplied = false;
Display._theme = theme;
}
},
/**
* Apply the theme to the provided element
* @param targetElement The target element to apply the theme (expected to be a <section> in the slides container)
* @param is_text Used to decide if the main area constraints should be applied
*/
applyTheme: function (targetElement, is_text=true) {
Display._themeApplied = true;
if (!Display._theme) {
return;
}
// Set slide transitions
var new_transition_type = "none",
new_transition_speed = "default";
if (!!theme.display_slide_transition && Display._doTransitions) {
switch (theme.display_slide_transition_type) {
if (!!Display._theme.display_slide_transition && Display._doTransitions) {
switch (Display._theme.display_slide_transition_type) {
case TransitionType.Fade:
new_transition_type = "fade";
break;
@ -928,7 +1005,7 @@ var Display = {
default:
new_transition_type = "fade";
}
switch (theme.display_slide_transition_speed) {
switch (Display._theme.display_slide_transition_speed) {
case TransitionSpeed.Normal:
new_transition_speed = "default";
break;
@ -941,7 +1018,7 @@ var Display = {
default:
new_transition_speed = "default";
}
switch (theme.display_slide_transition_direction) {
switch (Display._theme.display_slide_transition_direction) {
case TransitionDirection.Vertical:
new_transition_type += "-vertical";
break;
@ -949,95 +1026,102 @@ var Display = {
default:
new_transition_type += "-horizontal";
}
if (theme.display_slide_transition_reverse) {
if (Display._theme.display_slide_transition_reverse) {
new_transition_type += "-reverse";
}
}
Display.setTransition(new_transition_type, new_transition_speed);
var slides = targetElement.children;
for (var i = 0; i < slides.length; i++) {
slides[i].setAttribute("data-transition", new_transition_type);
slides[i].setAttribute("data-transition-speed", new_transition_speed);
}
// Set the background
var globalBackground = $("#global-background")[0];
var backgroundStyle = {};
var backgroundContent = "";
var backgroundHtml = "";
switch (theme.background_type) {
var globalBackground = $("#global-background")[0];
globalBackground.style.setProperty("background", "black");
switch (Display._theme.background_type) {
case BackgroundType.Transparent:
backgroundStyle.background = "transparent";
backgroundContent = "transparent";
globalBackground.style.setProperty("background", "transparent");
break;
case BackgroundType.Solid:
backgroundStyle.background = theme.background_color;
backgroundContent = Display._theme.background_color;
break;
case BackgroundType.Gradient:
switch (theme.background_direction) {
switch (Display._theme.background_direction) {
case GradientType.Horizontal:
backgroundStyle.background = _buildLinearGradient("left top", "left bottom",
theme.background_start_color,
theme.background_end_color);
backgroundContent = _buildLinearGradient("left top", "left bottom",
Display._theme.background_start_color,
Display._theme.background_end_color);
break;
case GradientType.Vertical:
backgroundStyle.background = _buildLinearGradient("left top", "right top",
theme.background_start_color,
theme.background_end_color);
backgroundContent = _buildLinearGradient("left top", "right top",
Display._theme.background_start_color,
Display._theme.background_end_color);
break;
case GradientType.LeftTop:
backgroundStyle.background = _buildLinearGradient("left top", "right bottom",
theme.background_start_color,
theme.background_end_color);
backgroundContent = _buildLinearGradient("left top", "right bottom",
Display._theme.background_start_color,
Display._theme.background_end_color);
break;
case GradientType.LeftBottom:
backgroundStyle.background = _buildLinearGradient("left bottom", "right top",
theme.background_start_color,
theme.background_end_color);
backgroundContent = _buildLinearGradient("left bottom", "right top",
Display._theme.background_start_color,
Display._theme.background_end_color);
break;
case GradientType.Circular:
backgroundStyle.background = _buildRadialGradient(window.innerWidth / 2, theme.background_start_color,
theme.background_end_color);
backgroundContent = _buildRadialGradient(window.innerWidth / 2, Display._theme.background_start_color,
Display._theme.background_end_color);
break;
default:
backgroundStyle.background = "#000";
backgroundContent = "#000";
}
break;
case BackgroundType.Image:
backgroundStyle["background-image"] = "url('" + theme.background_filename + "')";
console.warn(backgroundStyle["background-image"]);
backgroundContent = "url('" + Display._theme.background_filename + "')";
console.warn(backgroundContent);
break;
case BackgroundType.Video:
// never actually used since background type is overridden from video to transparent in window.py
backgroundStyle["background-color"] = theme.background_border_color;
backgroundHtml = "<video loop autoplay muted><source src='" + theme.background_filename + "'></video>";
backgroundContent = Display._theme.background_border_color;
backgroundHtml = "<video loop autoplay muted><source src='" + Display._theme.background_filename + "'></video>";
console.warn(backgroundHtml);
break;
default:
backgroundStyle.background = "#000";
}
globalBackground.style.cssText = "";
for (var bgKey in backgroundStyle) {
if (backgroundStyle.hasOwnProperty(bgKey)) {
globalBackground.style.setProperty(bgKey, backgroundStyle[bgKey]);
}
backgroundContent = "#000";
}
targetElement.style.cssText = "";
targetElement.setAttribute("data-background", backgroundContent);
targetElement.setAttribute("data-background-size", "cover");
if (!!backgroundHtml) {
globalBackground.innerHTML = backgroundHtml;
background.innerHTML = backgroundHtml;
}
// set up the main area
if (!is_text) {
// only transition and background for non text slides
return;
}
mainStyle = {};
if (!!theme.font_main_outline) {
mainStyle["-webkit-text-stroke"] = "" + theme.font_main_outline_size + "pt " +
theme.font_main_outline_color;
mainStyle["-webkit-text-fill-color"] = theme.font_main_color;
if (!!Display._theme.font_main_outline) {
mainStyle["-webkit-text-stroke"] = "" + Display._theme.font_main_outline_size + "pt " +
Display._theme.font_main_outline_color;
mainStyle["-webkit-text-fill-color"] = Display._theme.font_main_color;
}
// These need to be fixed, in the Python they use a width passed in as a parameter
mainStyle.width = theme.font_main_width + "px";
mainStyle.height = theme.font_main_height + "px";
mainStyle["margin-top"] = "" + theme.font_main_y + "px";
mainStyle.left = "" + theme.font_main_x + "px";
mainStyle.color = theme.font_main_color;
mainStyle["font-family"] = theme.font_main_name;
mainStyle["font-size"] = "" + theme.font_main_size + "pt";
mainStyle["font-style"] = !!theme.font_main_italics ? "italic" : "";
mainStyle["font-weight"] = !!theme.font_main_bold ? "bold" : "";
mainStyle["line-height"] = "" + (100 + theme.font_main_line_adjustment) + "%";
mainStyle.width = Display._theme.font_main_width + "px";
mainStyle.height = Display._theme.font_main_height + "px";
mainStyle["margin-top"] = "" + Display._theme.font_main_y + "px";
mainStyle.left = "" + Display._theme.font_main_x + "px";
mainStyle.color = Display._theme.font_main_color;
mainStyle["font-family"] = Display._theme.font_main_name;
mainStyle["font-size"] = "" + Display._theme.font_main_size + "pt";
mainStyle["font-style"] = !!Display._theme.font_main_italics ? "italic" : "";
mainStyle["font-weight"] = !!Display._theme.font_main_bold ? "bold" : "";
mainStyle["line-height"] = "" + (100 + Display._theme.font_main_line_adjustment) + "%";
// Using text-align-last because there is a <br> seperating each line
switch (theme.display_horizontal_align) {
switch (Display._theme.display_horizontal_align) {
case HorizontalAlign.Justify:
mainStyle["text-align"] = "justify";
mainStyle["text-align-last"] = "justify";
@ -1058,7 +1142,7 @@ var Display = {
mainStyle["text-align"] = "center";
mainStyle["text-align-last"] = "center";
}
switch (theme.display_vertical_align) {
switch (Display._theme.display_vertical_align) {
case VerticalAlign.Middle:
mainStyle["justify-content"] = "center";
break;
@ -1068,23 +1152,19 @@ var Display = {
case VerticalAlign.Bottom:
mainStyle["justify-content"] = "flex-end";
// This gets around the webkit scroll height bug
mainStyle["padding-bottom"] = "" + (theme.font_main_size / 8) + "px";
mainStyle["padding-bottom"] = "" + (Display._theme.font_main_size / 8) + "px";
break;
default:
mainStyle["justify-content"] = "center";
}
if (theme.hasOwnProperty('font_main_shadow_size') && !!theme.font_main_shadow) {
mainStyle["text-shadow"] = theme.font_main_shadow_color + " " + theme.font_main_shadow_size + "pt " +
theme.font_main_shadow_size + "pt";
if (Display._theme.hasOwnProperty('font_main_shadow_size') && !!Display._theme.font_main_shadow) {
mainStyle["text-shadow"] = Display._theme.font_main_shadow_color + " " + Display._theme.font_main_shadow_size + "pt " +
Display._theme.font_main_shadow_size + "pt";
}
var slidesDiv = $("section.text-slides");
if (slidesDiv.length > 0) {
slidesDiv = slidesDiv[0];
slidesDiv.style.cssText = "";
for (var mainKey in mainStyle) {
if (mainStyle.hasOwnProperty(mainKey)) {
slidesDiv.style.setProperty(mainKey, mainStyle[mainKey]);
}
targetElement.style.cssText = "";
for (var mainKey in mainStyle) {
if (mainStyle.hasOwnProperty(mainKey)) {
targetElement.style.setProperty(mainKey, mainStyle[mainKey]);
}
}
// Set up the footer
@ -1092,19 +1172,18 @@ var Display = {
"text-align": "left"
};
footerStyle.position = "absolute";
footerStyle.left = "" + theme.font_footer_x + "px";
footerStyle.top = "" + theme.font_footer_y + "px";
footerStyle.width = "" + theme.font_footer_width + "px";
footerStyle.height = "" + theme.font_footer_height + "px";
footerStyle.color = theme.font_footer_color;
footerStyle["font-family"] = theme.font_footer_name;
footerStyle["font-size"] = "" + theme.font_footer_size + "pt";
footerStyle["white-space"] = theme.font_footer_wrap ? "normal" : "nowrap";
var footer = $(".footer")[0];
footer.style.cssText = "";
footerStyle.left = "" + Display._theme.font_footer_x + "px";
footerStyle.top = "" + Display._theme.font_footer_y + "px";
footerStyle.width = "" + Display._theme.font_footer_width + "px";
footerStyle.height = "" + Display._theme.font_footer_height + "px";
footerStyle.color = Display._theme.font_footer_color;
footerStyle["font-family"] = Display._theme.font_footer_name;
footerStyle["font-size"] = "" + Display._theme.font_footer_size + "pt";
footerStyle["white-space"] = Display._theme.font_footer_wrap ? "normal" : "nowrap";
Display._footerContainer.style.cssText = "";
for (var footerKey in footerStyle) {
if (footerStyle.hasOwnProperty(footerKey)) {
footer.style.setProperty(footerKey, footerStyle[footerKey]);
Display._footerContainer.style.setProperty(footerKey, footerStyle[footerKey]);
}
}
},

View File

@ -812,7 +812,7 @@ class ThemePreviewRenderer(LogMixin, DisplayWindow):
"""
self.clear_slides()
self.log_debug('_text_fits_on_slide: 1\n{text}'.format(text=text))
self.run_javascript('Display.addTextSlide("v1", "{text}", "Dummy Footer");'
self.run_javascript('Display.setTextSlide("{text}");'
.format(text=text.replace('"', '\\"')), is_sync=True)
self.log_debug('_text_fits_on_slide: 2')
does_text_fits = self.run_javascript('Display.doesContentFit();', is_sync=True)

View File

@ -244,7 +244,9 @@ class DisplayWindow(QtWidgets.QWidget, RegistryProperties):
Add stuff after page initialisation
"""
js_is_display = str(self.is_display).lower()
self.run_javascript('Display.init({do_transitions});'.format(do_transitions=js_is_display))
item_transitions = str(self.settings.value('themes/item transitions')).lower()
self.run_javascript('Display.init({do_transitions}, {do_item_transitions});'
.format(do_transitions=js_is_display, do_item_transitions=item_transitions))
wait_for(lambda: self._is_initialised)
if self.scale != 1:
self.set_scale(self.scale)
@ -430,12 +432,6 @@ class DisplayWindow(QtWidgets.QWidget, RegistryProperties):
if self.is_display:
Registry().execute('live_display_active')
def blank_to_theme(self):
"""
Blank to theme
"""
self.run_javascript('Display.blankToTheme();')
def hide_display(self, mode=HideMode.Screen):
"""
Hide the display by making all layers transparent Store the images so they can be replaced when required
@ -450,9 +446,11 @@ class DisplayWindow(QtWidgets.QWidget, RegistryProperties):
if mode == HideMode.Screen:
self.setVisible(False)
elif mode == HideMode.Blank:
self.run_javascript('Display.blankToBlack();')
self.run_javascript('Display.toBlack();')
elif mode == HideMode.Theme:
self.run_javascript('Display.toTheme();')
else:
self.run_javascript('Display.blankToTheme();')
self.run_javascript('Display.toTransparent();')
if mode != HideMode.Screen:
if self.isHidden():
self.setVisible(True)

View File

@ -41,6 +41,7 @@ class HideMode(object):
Blank = 1
Theme = 2
Screen = 3
Transparent = 4
class DisplayControllerType(object):

View File

@ -40,7 +40,7 @@ from openlp.core.common.path import path_to_str
from openlp.core.common.registry import Registry, RegistryBase
from openlp.core.lib.serviceitem import ItemCapabilities
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui import DisplayControllerType
from openlp.core.ui import DisplayControllerType, HideMode
from openlp.core.ui.media import MediaState, ItemMediaInfo, MediaType, parse_optical_path, parse_devicestream_path, \
VIDEO_EXT, AUDIO_EXT
from openlp.core.ui.media.remote import register_views
@ -454,7 +454,9 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
controller.media_info.is_playing = True
if not controller.media_info.is_background:
display = self._define_display(controller)
display.setVisible(False)
display.hide_display(HideMode.Transparent)
controller._set_theme(controller.service_item)
display.load_verses([{"verse": "v1", "text": "", "footer": " "}])
return True
def tick(self, controller):
@ -466,9 +468,14 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
start_again = False
if controller.media_info.is_playing and controller.media_info.length > 0:
if controller.media_info.timer > controller.media_info.length:
self.media_stop(controller)
if controller.media_info.is_looping_playback:
start_again = True
else:
self.media_stop(controller)
elif controller.media_info.timer > controller.media_info.length - TICK_TIME * 4:
if not controller.media_info.is_looping_playback:
display = self._define_display(controller)
display.show_display()
controller.media_info.timer += TICK_TIME
seconds = controller.media_info.timer // 1000
minutes = seconds // 60
@ -479,7 +486,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
controller.position_label.setText(' %02d:%02d / %02d:%02d' %
(minutes, seconds, total_minutes, total_seconds))
if start_again:
self.media_play(controller, True)
controller.seek_slider.setSliderPosition(0)
self.media_play(controller, False)
def media_pause_msg(self, msg):
"""
@ -560,6 +568,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
controller.media_info.is_playing = False
controller.media_info.timer = 1000
controller.media_timer = 0
display = self._define_display(controller)
display.show_display()
def media_volume_msg(self, msg):
"""
@ -615,6 +625,8 @@ class MediaController(RegistryBase, LogMixin, RegistryProperties):
"""
self.set_controls_visible(controller, False)
if controller.controller_type in self.current_media_players:
display = self._define_display(controller)
display.show_display()
self.current_media_players[controller.controller_type].reset(controller)
self.current_media_players[controller.controller_type].set_visible(controller, False)
del self.current_media_players[controller.controller_type]

View File

@ -855,7 +855,7 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
self.preview_display.set_theme(theme_data, service_item_type=service_item.service_item_type)
# Set theme for displays
for display in self.displays:
display.set_theme(service_item.get_theme_data(), service_item_type=service_item.service_item_type)
display.set_theme(theme_data, service_item_type=service_item.service_item_type)
def _process_item(self, service_item, slide_no):
"""
@ -1168,20 +1168,9 @@ class SlideController(QtWidgets.QWidget, LogMixin, RegistryProperties):
Registry().execute('{text}_slide'.format(text=self.service_item.name.lower()),
[self.service_item, self.is_live, row])
else:
# to_display = self.service_item.get_rendered_frame(row)
if self.service_item.is_text():
for display in self.displays:
display.go_to_slide(row)
# self.display.text(to_display, row != old_selected_row)
else:
if start:
for display in self.displays:
display.load_images(self.service_item.slides)
# self.display.build_html(self.service_item, to_display)
else:
for display in self.displays:
display.go_to_slide(row)
# self.display.image(to_display)
for display in self.displays:
display.go_to_slide(row)
if not self.service_item.is_text():
# reset the store used to display first image
self.service_item.bg_image_bytes = None
self.selected_row = row

View File

@ -69,6 +69,9 @@ class ThemesTab(SettingsTab):
self.wrap_footer_check_box = QtWidgets.QCheckBox(self.universal_group_box)
self.wrap_footer_check_box.setObjectName('wrap_footer_check_box')
self.universal_group_box_layout.addWidget(self.wrap_footer_check_box)
self.item_transitions_check_box = QtWidgets.QCheckBox(self.universal_group_box)
self.item_transitions_check_box.setObjectName('item_transitions_check_box')
self.universal_group_box_layout.addWidget(self.item_transitions_check_box)
self.left_layout.addWidget(self.universal_group_box)
self.left_layout.addStretch()
self.level_group_box = QtWidgets.QGroupBox(self.right_column)
@ -115,6 +118,7 @@ class ThemesTab(SettingsTab):
self.global_group_box.setTitle(translate('OpenLP.ThemesTab', 'Global Theme'))
self.universal_group_box.setTitle(translate('OpenLP.ThemesTab', 'Universal Settings'))
self.wrap_footer_check_box.setText(translate('OpenLP.ThemesTab', '&Wrap footer text'))
self.item_transitions_check_box.setText(translate('OpenLP.ThemesTab', '&Transition between service items'))
self.level_group_box.setTitle(translate('OpenLP.ThemesTab', 'Theme Level'))
self.song_level_radio_button.setText(translate('OpenLP.ThemesTab', 'S&ong Level'))
self.song_level_label.setText(
@ -139,6 +143,7 @@ class ThemesTab(SettingsTab):
self.theme_level = self.settings.value('theme level')
self.global_theme = self.settings.value('global theme')
self.wrap_footer_check_box.setChecked(self.settings.value('wrap footer'))
self.item_transitions_check_box.setChecked(self.settings.value('item transitions'))
self.settings.endGroup()
if self.theme_level == ThemeLevel.Global:
self.global_level_radio_button.setChecked(True)
@ -155,6 +160,7 @@ class ThemesTab(SettingsTab):
self.settings.setValue('theme level', self.theme_level)
self.settings.setValue('global theme', self.global_theme)
self.settings.setValue('wrap footer', self.wrap_footer_check_box.isChecked())
self.settings.setValue('item transitions', self.item_transitions_check_box.isChecked())
self.settings.endGroup()
self.renderer.set_theme_level(self.theme_level)
if self.tab_visited:

View File

@ -32,6 +32,7 @@ from PyQt5 import QtCore
sys.modules['PyQt5.QtWebEngineWidgets'] = MagicMock()
from openlp.core.display.window import DisplayWindow
from openlp.core.ui import HideMode
@patch('PyQt5.QtWidgets.QVBoxLayout')
@ -103,6 +104,31 @@ def test_set_scale_initialised(mocked_webengine, mocked_addWidget, mock_settings
display_window.run_javascript.assert_called_once_with('Display.setScale(50.0);')
@patch('PyQt5.QtWidgets.QVBoxLayout')
@patch('openlp.core.display.webengine.WebEngineView')
def test_after_loaded(mocked_webengine, mocked_addWidget, mock_settings):
"""
Test the correct steps are taken when the webview is loaded
"""
# GIVEN: An initialised display window and settings for item transitions returns true
display_window = DisplayWindow()
display_window.is_display = True
mock_settings.value.return_value = True
display_window.scale = 2
display_window._is_initialised = True
display_window.run_javascript = MagicMock()
display_window.set_scale = MagicMock()
display_window.set_startup_screen = MagicMock()
# WHEN: after_loaded is run
display_window.after_loaded()
# THEN: The following functions should have been called
display_window.run_javascript.assert_called_once_with('Display.init(true, true);')
display_window.set_scale.assert_called_once_with(2)
display_window.set_startup_screen.assert_called_once()
@patch('PyQt5.QtWidgets.QVBoxLayout')
@patch('openlp.core.display.webengine.WebEngineView')
@patch.object(time, 'time')
@ -146,3 +172,75 @@ def test_run_javascript_sync_no_wait(mock_time, mocked_webengine, mocked_addWidg
assert result == 1234
webengine_page.runJavaScript.assert_called_once()
mock_time.sleep.assert_not_called()
@patch('PyQt5.QtWidgets.QVBoxLayout')
@patch('openlp.core.display.webengine.WebEngineView')
def test_hide_display_to_screen(mocked_webengine, mocked_addWidget, mock_settings):
"""
Test hide to screen in the hide_display function
"""
# GIVEN:
display_window = DisplayWindow()
display_window.setVisible = MagicMock()
# WHEN: Hide display is run with no mode (should default to Screen)
display_window.hide_display()
# THEN: Should hide the display and set the hide mode
display_window.setVisible.assert_called_once_with(False)
assert display_window.hide_mode == HideMode.Screen
@patch('PyQt5.QtWidgets.QVBoxLayout')
@patch('openlp.core.display.webengine.WebEngineView')
def test_hide_display_to_blank(mocked_webengine, mocked_addWidget, mock_settings):
"""
Test hide to screen in the hide_display function
"""
# GIVEN:
display_window = DisplayWindow()
display_window.run_javascript = MagicMock()
# WHEN: Hide display is run with HideMode.Blank
display_window.hide_display(HideMode.Blank)
# THEN: Should run the correct javascript on the display and set the hide mode
display_window.run_javascript.assert_called_once_with('Display.toBlack();')
assert display_window.hide_mode == HideMode.Blank
@patch('PyQt5.QtWidgets.QVBoxLayout')
@patch('openlp.core.display.webengine.WebEngineView')
def test_hide_display_to_theme(mocked_webengine, mocked_addWidget, mock_settings):
"""
Test hide to screen in the hide_display function
"""
# GIVEN:
display_window = DisplayWindow()
display_window.run_javascript = MagicMock()
# WHEN: Hide display is run with HideMode.Theme
display_window.hide_display(HideMode.Theme)
# THEN: Should run the correct javascript on the display and set the hide mode
display_window.run_javascript.assert_called_once_with('Display.toTheme();')
assert display_window.hide_mode == HideMode.Theme
@patch('PyQt5.QtWidgets.QVBoxLayout')
@patch('openlp.core.display.webengine.WebEngineView')
def test_hide_display_to_transparent(mocked_webengine, mocked_addWidget, mock_settings):
"""
Test hide to screen in the hide_display function
"""
# GIVEN:
display_window = DisplayWindow()
display_window.run_javascript = MagicMock()
# WHEN: Hide display is run with HideMode.Transparent
display_window.hide_display(HideMode.Transparent)
# THEN: Should run the correct javascript on the display and set the hide mode
display_window.run_javascript.assert_called_once_with('Display.toTransparent();')
assert display_window.hide_mode == HideMode.Transparent

View File

@ -324,3 +324,23 @@ def test_setup_display(MockItemMediaInfo, media_env):
assert controller.has_audio is False
media_env.media_controller._define_display.assert_called_once_with(controller)
media_env.media_controller.vlc_player.setup(controller, mocked_display, False)
def test_media_play(media_env):
"""
Test that the display/controllers are set up correctly
"""
# GIVEN: A mocked controller where is_background is false
media_env.current_media_players = MagicMock()
Registry().register('settings', MagicMock())
media_env.live_timer = MagicMock()
mocked_controller = MagicMock()
mocked_controller.media_info.is_background = False
# WHEN: media_play is called
result = media_env.media_play(mocked_controller)
# THEN: The web display should become transparent (only tests that the theme is reset here)
# And the function should return true to indicate success
assert result is True
mocked_controller._set_theme.assert_called_once()

View File

@ -43,6 +43,29 @@ def test_initial_slide_controller(registry):
assert slide_controller.is_live is False, 'The base slide controller should not be a live controller'
def test_slide_selected(settings):
"""
Test the slide selected method
"""
# GIVEN: A new SlideController instance on slide 4 of 10, and is not a command
slide_controller = SlideController(None)
slide_controller.update_preview = MagicMock()
slide_controller.slide_selected_lock = MagicMock()
slide_controller.service_item = MagicMock()
slide_controller.service_item.is_command.return_value = False
slide_controller.preview_widget = MagicMock()
slide_controller.preview_widget.slide_count.return_value = 10
slide_controller.preview_widget.current_slide_number.return_value = 4
mocked_display = MagicMock()
slide_controller.displays = [mocked_display]
# WHEN: The slide_selected method is run
slide_controller.slide_selected(True)
# THEN: The display is updated with the slide number
mocked_display.go_to_slide.assert_called_once_with(4)
def test_text_service_item_blank(settings):
"""
Test that loading a text-based service item into the slide controller sets the correct blank menu

View File

@ -76,6 +76,7 @@ describe("The function", function () {
});
describe("The Display object", function () {
it("should start with a blank _slides object", function () {
expect(Display._slides).toEqual({});
});
@ -107,6 +108,8 @@ describe("The Display object", function () {
it("should initialise Reveal when init is called", function () {
spyOn(Reveal, "initialize");
document.body.innerHTML = "";
_createDiv({"id": "global-background"});
Display.init();
expect(Reveal.initialize).toHaveBeenCalled();
});
@ -123,16 +126,18 @@ describe("The Display object", function () {
expect(Reveal.slide).toHaveBeenCalledWith(0);
});
it("should have a setTransition() method", function () {
expect(Display.setTransition).toBeDefined();
it("should have a setItemTransition() method", function () {
expect(Display.setItemTransition).toBeDefined();
});
it("should have a correctly functioning clearSlides() method", function () {
expect(Display.clearSlides).toBeDefined();
document.body.innerHTML = "";
var slidesDiv = _createDiv({"class": "slides"});
slidesDiv.innerHTML = "<section><p></p></section>";
Display._slidesContainer = slidesDiv;
var footerDiv = _createDiv({"class": "footer"});
Display._footerContainer = footerDiv;
Display.clearSlides();
expect($(".slides")[0].innerHTML).toEqual("");
@ -167,42 +172,48 @@ describe("Transitions", function () {
Display._theme = null;
});
it("should have a correctly functioning setTransition() method", function () {
it("should have a correctly functioning setItemTransition() method", function () {
spyOn(Reveal, "configure");
Display.setTransition("fade", "slow");
expect(Reveal.configure).toHaveBeenCalledWith({"transition": "fade", "transitionSpeed": "slow"});
Display.setItemTransition(true);
expect(Reveal.configure).toHaveBeenCalledWith({"backgroundTransition": "fade", "transitionSpeed": "default"});
});
it("should have enabled transitions when _doTransitions is true and setTheme is run", function () {
spyOn(Display, "setTransition");
it("should have enabled transitions when _doTransitions is true and applyTheme is run", function () {
Display._doTransitions = true;
var theme = {
"display_slide_transition": true,
"display_slide_transition_type": TransitionType.Slide,
"display_slide_transition_speed": TransitionSpeed.Fast
}
Display.setTheme(theme);
var slidesDiv = _createDiv({"class": "slides"});
slidesDiv.innerHTML = "<section><section><p></p></section></section>";
Display._slidesContainer = slidesDiv;
expect(Display.setTransition).toHaveBeenCalledWith("slide-horizontal", "fast");
Display.applyTheme(Display._slidesContainer.children[0])
expect(Display._slidesContainer.children[0].children[0].getAttribute("data-transition")).toEqual("slide-horizontal");
expect(Display._slidesContainer.children[0].children[0].getAttribute("data-transition-speed")).toEqual("fast");
});
it("should have not enabled transitions when init() with no transitions and setTheme is run", function () {
spyOn(Display, "setTransition");
Display._doTransitions = false;
var theme = {
"display_slide_transition": true,
"display_slide_transition_type": TransitionType.Slide,
"display_slide_transition_speed": TransitionSpeed.Fast,
}
Display.setTheme(theme);
var slidesDiv = _createDiv({"class": "slides"});
slidesDiv.innerHTML = "<section><section><p></p></section></section>";
Display._slidesContainer = slidesDiv;
expect(Display.setTransition).toHaveBeenCalledWith("none", "default");
Display.applyTheme(Display._slidesContainer.children[0])
expect(Display._slidesContainer.children[0].children[0].getAttribute("data-transition")).toEqual("none");
});
it("should have enabled transitions in the correct direction", function () {
spyOn(Display, "setTransition");
Display._doTransitions = true;
var theme = {
"display_slide_transition": true,
@ -211,10 +222,15 @@ describe("Transitions", function () {
"display_slide_transition_direction": TransitionDirection.Vertical,
"display_slide_transition_reverse": true,
}
Display.setTheme(theme);
var slidesDiv = _createDiv({"class": "slides"});
slidesDiv.innerHTML = "<section><section><p></p></section></section>";
Display._slidesContainer = slidesDiv;
expect(Display.setTransition).toHaveBeenCalledWith("convex-vertical-reverse", "slow");
Display.applyTheme(Display._slidesContainer.children[0])
expect(Display._slidesContainer.children[0].children[0].getAttribute("data-transition")).toEqual("convex-vertical-reverse");
expect(Display._slidesContainer.children[0].children[0].getAttribute("data-transition-speed")).toEqual("slow");
});
});
@ -504,63 +520,49 @@ describe("Display.alertAnimationEndEvent", function () {
});
});
describe("Display.addTextSlide", function () {
describe("Display.setTextSlide", function () {
beforeEach(function() {
document.body.innerHTML = "";
_createDiv({"class": "slides"});
_createDiv({"class": "footer"});
var slides_container = _createDiv({"class": "slides"});
var footer_container = _createDiv({"class": "footer"});
Display._slidesContainer = slides_container;
Display._footerContainer = footer_container;
Display._slides = {};
});
it("should add a new slide", function () {
var verse = "v1",
text = "Amazing grace,\nhow sweet the sound",
footer = "Public Domain";
var text = "Amazing grace,\nhow sweet the sound";
spyOn(Display, "reinit");
Display.addTextSlide(verse, text, footer);
Display.setTextSlide(text);
expect(Display._slides[verse]).toEqual(0);
expect(Display._slides["test-slide"]).toEqual(0);
expect($(".slides > section > section").length).toEqual(1);
expect($(".slides > section > section")[0].innerHTML).toEqual(_prepareText(text));
expect(Display.reinit).toHaveBeenCalled();
});
it("should add a new slide without calling reinit()", function () {
var verse = "v1",
text = "Amazing grace,\nhow sweet the sound",
footer = "Public Domain";
spyOn(Display, "reinit");
Display.addTextSlide(verse, text, footer, false);
expect(Display._slides[verse]).toEqual(0);
expect($(".slides > section > section").length).toEqual(1);
expect($(".slides > section > section")[0].innerHTML).toEqual(_prepareText(text));
expect(Display.reinit).not.toHaveBeenCalled();
});
it("should update an existing slide", function () {
var verse = "v1",
text = "Amazing grace, how sweet the sound\nThat saved a wretch like me",
footer = "Public Domain";
Display.addTextSlide(verse, "Amazing grace,\nhow sweet the sound", footer, false);
var text = "That saved a wretch\nlike me";
spyOn(Display, "reinit");
Display.setTextSlide("Amazing grace,\nhow sweet the sound");
Display.addTextSlide(verse, text, footer, true);
Display.setTextSlide(text);
expect(Display._slides[verse]).toEqual(0);
expect(Display._slides["test-slide"]).toEqual(0);
expect($(".slides > section > section").length).toEqual(1);
expect($(".slides > section > section")[0].innerHTML).toEqual(_prepareText(text));
expect(Display.reinit).toHaveBeenCalledTimes(0);
expect(Display.reinit).toHaveBeenCalledTimes(1); // only called once for the first setTextSlide
});
});
describe("Display.setTextSlides", function () {
beforeEach(function() {
document.body.innerHTML = "";
_createDiv({"class": "slides"});
_createDiv({"class": "footer"});
var slides_container = _createDiv({"class": "slides"});
var footer_container = _createDiv({"class": "footer"});
Display._slidesContainer = slides_container;
Display._footerContainer = footer_container;
_createDiv({"id": "global-background"});
Display._slides = {};
});
@ -581,15 +583,16 @@ describe("Display.setTextSlides", function () {
}
];
spyOn(Display, "clearSlides");
spyOn(Display, "reinit");
spyOn(Reveal, "sync");
spyOn(Reveal, "slide");
Display.setTextSlides(slides);
expect(Display.clearSlides).toHaveBeenCalledTimes(1);
expect(Display.clearSlides).toHaveBeenCalledTimes(0);
expect(Display._slides["v1"]).toEqual(0);
expect(Display._slides["v2"]).toEqual(1);
expect($(".slides > section > section").length).toEqual(2);
expect(Display.reinit).toHaveBeenCalledTimes(1);
expect(Reveal.sync).toHaveBeenCalledTimes(1);
});
it("should correctly set outline width", function () {
@ -607,7 +610,7 @@ describe("Display.setTextSlides", function () {
'font_main_outline_size': 42,
'font_main_outline_color': 'red'
};
spyOn(Display, "reinit");
spyOn(Reveal, "sync");
spyOn(Reveal, "slide");
Display.setTheme(theme);
@ -633,7 +636,7 @@ describe("Display.setTextSlides", function () {
'display_horizontal_align': 3,
'display_vertical_align': 1
};
spyOn(Display, "reinit");
spyOn(Reveal, "sync");
spyOn(Reveal, "slide");
Display.setTheme(theme);
@ -659,7 +662,7 @@ describe("Display.setTextSlides", function () {
'font_main_shadow_color': "#000",
'font_main_shadow_size': 5
};
spyOn(Display, "reinit");
spyOn(Reveal, "sync");
spyOn(Reveal, "slide");
Display.setTheme(theme);
@ -684,7 +687,7 @@ describe("Display.setTextSlides", function () {
'font_main_shadow_color': "#000",
'font_main_shadow_size': 5
};
spyOn(Display, "reinit");
spyOn(Reveal, "sync");
spyOn(Reveal, "slide");
Display.setTheme(theme);
@ -710,7 +713,7 @@ describe("Display.setTextSlides", function () {
'font_main_width': 1230,
'font_main_height': 4560
};
spyOn(Display, "reinit");
spyOn(Reveal, "sync");
spyOn(Reveal, "slide");
Display.setTheme(theme);
@ -727,20 +730,21 @@ describe("Display.setTextSlides", function () {
describe("Display.setImageSlides", function () {
beforeEach(function() {
document.body.innerHTML = "";
_createDiv({"class": "slides"});
_createDiv({"class": "footer"});
var slides_container = _createDiv({"class": "slides"});
var footer_container = _createDiv({"class": "footer"});
Display._slidesContainer = slides_container;
Display._footerContainer = footer_container;
_createDiv({"id": "global-background"});
Display._slides = {};
});
it("should add a list of images", function () {
var slides = [{"path": "file:///openlp1.jpg"}, {"path": "file:///openlp2.jpg"}];
spyOn(Display, "clearSlides");
spyOn(Display, "reinit");
spyOn(Reveal, "sync");
spyOn(Reveal, "slide");
Display.setImageSlides(slides);
expect(Display.clearSlides).toHaveBeenCalledTimes(1);
expect(Display._slides["0"]).toEqual(0);
expect(Display._slides["1"]).toEqual(1);
expect($(".slides > section > section").length).toEqual(2);
@ -749,30 +753,30 @@ describe("Display.setImageSlides", function () {
expect($(".slides > section > section > img")[0].getAttribute("style")).toEqual("max-width: 100%; max-height: 100%; margin: 0; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);")
expect($(".slides > section > section > img")[1].getAttribute("src")).toEqual("file:///openlp2.jpg")
expect($(".slides > section > section > img")[1].getAttribute("style")).toEqual("max-width: 100%; max-height: 100%; margin: 0; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);")
expect(Display.reinit).toHaveBeenCalledTimes(1);
expect(Reveal.sync).toHaveBeenCalledTimes(1);
});
});
describe("Display.setVideo", function () {
beforeEach(function() {
document.body.innerHTML = "";
_createDiv({"class": "slides"});
var slides_container = _createDiv({"class": "slides"});
Display._slidesContainer = slides_container;
_createDiv({"id": "global-background"});
Display._slides = {};
});
it("should add a video to the page", function () {
var video = {"path": "file:///video.mp4"};
spyOn(Display, "clearSlides");
spyOn(Display, "reinit");
spyOn(Reveal, "sync");
spyOn(Reveal, "slide");
Display.setVideo(video);
expect(Display.clearSlides).toHaveBeenCalledTimes(1);
expect($(".slides > section").length).toEqual(1);
expect($(".slides > section > video").length).toEqual(1);
expect($(".slides > section > video")[0].src).toEqual("file:///video.mp4")
expect(Display.reinit).toHaveBeenCalledTimes(1);
expect(Reveal.sync).toHaveBeenCalledTimes(1);
});
});