diff --git a/openlp/core/display/html/display.css b/openlp/core/display/html/display.css index cb79612e6..d45aca116 100644 --- a/openlp/core/display/html/display.css +++ b/openlp/core/display/html/display.css @@ -98,3 +98,387 @@ sup { transition: opacity 0.5s linear; z-index: 100; } + +/********************************************* + * Transition overrides to allow different directions + *********************************************/ +/********************************************* + * SLIDE TRANSITION + * Aliased 'linear' for backwards compatibility + *********************************************/ +.reveal .slides section[data-transition~=concave].stack, +.reveal[class~=slide] .slides section.stack { + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal .slides > section[data-transition=slide].past, +.reveal .slides > section[data-transition~=slide-out].past, +.reveal.slide .slides > section:not([data-transition]).past, +.reveal .slides > section > section[data-transition=slide-horizontal].past, +.reveal .slides > section > section[data-transition~=slide-horizontal-out].past, +.reveal.slide-horizontal .slides > section > section:not([data-transition]).past, +.reveal .slides > section > section[data-transition=slide-horizontal-reverse].future, +.reveal .slides > section > section[data-transition~=slide-horizontal-reverse-in].future, +.reveal.slide-horizontal-reverse .slides > section > section:not([data-transition]).future { + -webkit-transform: translate(-150%, 0); + transform: translate(-150%, 0); } + +.reveal .slides > section[data-transition=slide].future, +.reveal .slides > section[data-transition~=slide-in].future, +.reveal.slide .slides > section:not([data-transition]).future, +.reveal .slides > section > section[data-transition=slide-horizontal].future, +.reveal .slides > section > section[data-transition~=slide-horizontal-in].future, +.reveal.slide-horizontal .slides > section > section:not([data-transition]).future, +.reveal .slides > section > section[data-transition=slide-horizontal-reverse].past, +.reveal .slides > section > section[data-transition~=slide-horizontal-reverse-out].past, +.reveal.slide-horizontal-reverse .slides > section > section:not([data-transition]).past { + -webkit-transform: translate(150%, 0); + transform: translate(150%, 0); } + +.reveal .slides > section > section[data-transition=slide-vertical].past, +.reveal .slides > section > section[data-transition~=slide-vertical-out].past, +.reveal.slide-vertical .slides > section > section:not([data-transition]).past, +.reveal .slides > section > section[data-transition=slide-vertical-reverse].future, +.reveal .slides > section > section[data-transition~=slide-vertical-reverse-in].future, +.reveal.slide-vertical-reverse .slides > section > section:not([data-transition]).future { + -webkit-transform: translate(0, -150%); + transform: translate(0, -150%); } + +.reveal .slides > section > section[data-transition=slide-vertical].future, +.reveal .slides > section > section[data-transition~=slide-vertical-in].future, +.reveal.slide-vertical .slides > section > section:not([data-transition]).future, +.reveal .slides > section > section[data-transition=slide-vertical-reverse].past, +.reveal .slides > section > section[data-transition~=slide-vertical-reverse-out].past, +.reveal.slide-vertical-reverse .slides > section > section:not([data-transition]).past { + -webkit-transform: translate(0, 150%); + transform: translate(0, 150%); } + +/********************************************* + * CONVEX TRANSITION + * Aliased 'default' for backwards compatibility + *********************************************/ +.reveal .slides section[data-transition~=convex].stack, +.reveal[class~=convex] .slides section.stack { + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal .slides > section[data-transition=convex].past, +.reveal .slides > section[data-transition~=convex-out].past, +.reveal.convex .slides > section:not([data-transition]).past, +.reveal .slides > section > section[data-transition=convex-horizontal].past, +.reveal .slides > section > section[data-transition~=convex-horizontal-out].past, +.reveal.convex-horizontal .slides > section > section:not([data-transition]).past, +.reveal .slides > section > section[data-transition=convex-horizontal-reverse].future, +.reveal .slides > section > section[data-transition~=convex-horizontal-reverse-in].future, +.reveal.convex-horizontal-reverse .slides > section > section:not([data-transition]).future { + -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) rotateY(-90deg) translate3d(-100%, 0, 0); } + +.reveal .slides > section[data-transition=convex].future, +.reveal .slides > section[data-transition~=convex-in].future, +.reveal.convex .slides > section:not([data-transition]).future, +.reveal .slides > section > section[data-transition=convex-horizontal].future, +.reveal .slides > section > section[data-transition~=convex-horizontal-in].future, +.reveal.convex-horizontal .slides > section > section:not([data-transition]).future, +.reveal .slides > section > section[data-transition=convex-horizontal-reverse].past, +.reveal .slides > section > section[data-transition~=convex-horizontal-reverse-out].past, +.reveal.convex-horizontal-reverse .slides > section > section:not([data-transition]).past { + -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) rotateY(90deg) translate3d(100%, 0, 0); } + +.reveal .slides > section > section[data-transition=convex-vertical].past, +.reveal .slides > section > section[data-transition~=convex-vertical-out].past, +.reveal.convex-vertical .slides > section > section:not([data-transition]).past, +.reveal .slides > section > section[data-transition=convex-vertical-reverse].future, +.reveal .slides > section > section[data-transition~=convex-vertical-reverse-in].future, +.reveal.convex-vertical-reverse .slides > section > section:not([data-transition]).future { + -webkit-transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); + transform: translate3d(0, -300px, 0) rotateX(70deg) translate3d(0, -300px, 0); } + +.reveal .slides > section > section[data-transition=convex-vertical].future, +.reveal .slides > section > section[data-transition~=convex-vertical-in].future, +.reveal.convex-vertical .slides > section > section:not([data-transition]).future, +.reveal .slides > section > section[data-transition=convex-vertical-reverse].past, +.reveal .slides > section > section[data-transition~=convex-vertical-reverse-out].past, +.reveal.convex-vertical-reverse .slides > section > section:not([data-transition]).past { + -webkit-transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); + transform: translate3d(0, 300px, 0) rotateX(-70deg) translate3d(0, 300px, 0); } + +/********************************************* + * CONCAVE TRANSITION + *********************************************/ +.reveal .slides section[data-transition~=concave].stack, +.reveal[class~=concave] .slides section.stack { + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal .slides > section[data-transition=concave-vertical].past, +.reveal .slides > section[data-transition~=concave-vertical-out].past, +.reveal.concave-vertical .slides > section:not([data-transition]).past, +.reveal .slides > section > section[data-transition=concave-horizontal].past, +.reveal .slides > section > section[data-transition~=concave-horizontal-out].past, +.reveal.concave-horizontal .slides > section > section:not([data-transition]).past, +.reveal .slides > section > section[data-transition=concave-horizontal-reverse].future, +.reveal .slides > section > section[data-transition~=concave-horizontal-reverse-in].future, +.reveal.concave-horizontal-reverse .slides > section > section:not([data-transition]).future { + -webkit-transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0) rotateY(90deg) translate3d(-100%, 0, 0); } + +.reveal .slides > section[data-transition=concave-vertical].future, +.reveal .slides > section[data-transition~=concave-vertical-in].future, +.reveal.concave-vertical .slides > section:not([data-transition]).future, +.reveal .slides > section > section[data-transition=concave-horizontal].future, +.reveal .slides > section > section[data-transition~=concave-horizontal-in].future, +.reveal.concave-horizontal .slides > section > section:not([data-transition]).future, +.reveal .slides > section > section[data-transition=concave-horizontal-reverse].past, +.reveal .slides > section > section[data-transition~=concave-horizontal-reverse-out].past, +.reveal.concave-horizontal-reverse .slides > section > section:not([data-transition]).past { + -webkit-transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0) rotateY(-90deg) translate3d(100%, 0, 0); } + +.reveal .slides > section > section[data-transition=concave-vertical].past, +.reveal .slides > section > section[data-transition~=concave-vertical-out].past, +.reveal.concave-vertical .slides > section > section:not([data-transition]).past, +.reveal .slides > section > section[data-transition=concave-vertical-reverse].future, +.reveal .slides > section > section[data-transition~=concave-vertical-reverse-in].future, +.reveal.concave-vertical-reverse .slides > section > section:not([data-transition]).future { + -webkit-transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); + transform: translate3d(0, -80%, 0) rotateX(-70deg) translate3d(0, -80%, 0); } + +.reveal .slides > section > section[data-transition=concave-vertical].future, +.reveal .slides > section > section[data-transition~=concave-vertical-in].future, +.reveal.concave-vertical .slides > section > section:not([data-transition]).future, +.reveal .slides > section > section[data-transition=concave-vertical-reverse].past, +.reveal .slides > section > section[data-transition~=concave-vertical-reverse-out].past, +.reveal.concave-vertical-reverse .slides > section > section:not([data-transition]).past { + -webkit-transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); + transform: translate3d(0, 80%, 0) rotateX(70deg) translate3d(0, 80%, 0); } + +/********************************************* + * ZOOM TRANSITION + *********************************************/ +.reveal .slides section[data-transition~=zoom], +.reveal[class~=zoom] .slides section:not([data-transition]) { + transition-timing-function: ease; } + +.reveal .slides > section[data-transition=zoom].past, +.reveal .slides > section[data-transition~=zoom-out].past, +.reveal.zoom .slides > section:not([data-transition]).past, +.reveal .slides > section > section[data-transition=zoom-horizontal].past, +.reveal .slides > section > section[data-transition~=zoom-horizontal-out].past, +.reveal.zoom-horizontal .slides > section > section:not([data-transition]).past, +.reveal .slides > section > section[data-transition=zoom-horizontal-reverse].future, +.reveal .slides > section > section[data-transition~=zoom-horizontal-reverse-in].future, +.reveal.zoom-horizontal-reverse .slides > section > section:not([data-transition]).future { + visibility: hidden; + -webkit-transform: scale(16); + transform: scale(16); } + +.reveal .slides > section[data-transition=zoom].future, +.reveal .slides > section[data-transition~=zoom-in].future, +.reveal.zoom .slides > section:not([data-transition]).future, +.reveal .slides > section > section[data-transition=zoom-horizontal].future, +.reveal .slides > section > section[data-transition~=zoom-horizontal-in].future, +.reveal.zoom-horizontal .slides > section > section:not([data-transition]).future, +.reveal .slides > section > section[data-transition=zoom-horizontal-reverse].past, +.reveal .slides > section > section[data-transition~=zoom-horizontal-reverse-out].past, +.reveal.zoom-horizontal-reverse .slides > section > section:not([data-transition]).past { + visibility: hidden; + -webkit-transform: scale(0.2); + transform: scale(0.2); } + +.reveal .slides > section > section[data-transition=zoom-vertical].past, +.reveal .slides > section > section[data-transition~=zoom-vertical-out].past, +.reveal.zoom-vertical .slides > section > section:not([data-transition]).past, +.reveal .slides > section > section[data-transition=zoom-vertical-reverse].future, +.reveal .slides > section > section[data-transition~=zoom-vertical-reverse-in].future, +.reveal.zoom-vertical-reverse .slides > section > section:not([data-transition]).future { + -webkit-transform: scale(16); + transform: scale(16); } + +.reveal .slides > section > section[data-transition=zoom-vertical].future, +.reveal .slides > section > section[data-transition~=zoom-vertical-in].future, +.reveal.zoom-vertical .slides > section > section:not([data-transition]).future, +.reveal .slides > section > section[data-transition=zoom-vertical-reverse].past, +.reveal .slides > section > section[data-transition~=zoom-vertical-reverse-out].past, +.reveal.zoom-vertical-reverse .slides > section > section:not([data-transition]).past { + -webkit-transform: scale(0.2); + transform: scale(0.2); } + +/********************************************* + * CUBE TRANSITION + * + * WARNING: + * this is deprecated and will be removed in a + * future version. + *********************************************/ +.reveal[class~=cube] .slides { + -webkit-perspective: 1300px; + perspective: 1300px; } + +.reveal[class~=cube] .slides section { + padding: 30px; + min-height: 700px; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + box-sizing: border-box; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal.center[class~=cube] .slides section { + min-height: 0; } + +.reveal[class~=cube] .slides section:not(.stack):before { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 100%; + left: 0; + top: 0; + background: rgba(0, 0, 0, 0.1); + border-radius: 4px; + -webkit-transform: translateZ(-20px); + transform: translateZ(-20px); } + +.reveal[class~=cube] .slides section:not(.stack):after { + content: ''; + position: absolute; + display: block; + width: 90%; + height: 30px; + left: 5%; + bottom: 0; + background: none; + z-index: 1; + border-radius: 4px; + box-shadow: 0px 95px 25px rgba(0, 0, 0, 0.2); + -webkit-transform: translateZ(-90px) rotateX(65deg); + transform: translateZ(-90px) rotateX(65deg); } + +.reveal[class~=cube] .slides > section.stack { + padding: 0; + background: none; } + +.reveal.cube .slides > section.past, +.reveal.cube-horizontal .slides > section > section.past, +.reveal.cube-horizontal-reverse .slides > section > section.future { + -webkit-transform-origin: 100% 0%; + transform-origin: 100% 0%; + -webkit-transform: translate3d(-100%, 0, 0) rotateY(-90deg); + transform: translate3d(-100%, 0, 0) rotateY(-90deg); } + +.reveal.cube .slides > section.future, +.reveal.cube-horizontal .slides > section > section.future, +.reveal.cube-horizontal-reverse .slides > section > section.past { + -webkit-transform-origin: 0% 0%; + transform-origin: 0% 0%; + -webkit-transform: translate3d(100%, 0, 0) rotateY(90deg); + transform: translate3d(100%, 0, 0) rotateY(90deg); } + +.reveal.cube-vertical .slides > section > section.past, +.reveal.cube-vertical-reverse .slides > section > section.future { + -webkit-transform-origin: 0% 100%; + transform-origin: 0% 100%; + -webkit-transform: translate3d(0, -100%, 0) rotateX(90deg); + transform: translate3d(0, -100%, 0) rotateX(90deg); } + +.reveal.cube-vertical .slides > section > section.future, +.reveal.cube-vertical-reverse .slides > section > section.past { + -webkit-transform-origin: 0% 0%; + transform-origin: 0% 0%; + -webkit-transform: translate3d(0, 100%, 0) rotateX(-90deg); + transform: translate3d(0, 100%, 0) rotateX(-90deg); } + +/********************************************* + * PAGE TRANSITION + * + * WARNING: + * this is deprecated and will be removed in a + * future version. + *********************************************/ +.reveal[class~=page] .slides { + -webkit-perspective-origin: 0% 50%; + perspective-origin: 0% 50%; + -webkit-perspective: 3000px; + perspective: 3000px; } + +.reveal[class~=page] .slides section { + padding: 30px; + min-height: 700px; + box-sizing: border-box; + -webkit-transform-style: preserve-3d; + transform-style: preserve-3d; } + +.reveal[class~=page] .slides section.past { + z-index: 12; } + +.reveal[class~=page] .slides section:not(.stack):before { + content: ''; + position: absolute; + display: block; + width: 100%; + height: 100%; + left: 0; + top: 0; + background: rgba(0, 0, 0, 0.1); + -webkit-transform: translateZ(-20px); + transform: translateZ(-20px); } + +.reveal[class~=page] .slides section:not(.stack):after { + content: ''; + position: absolute; + display: block; + width: 90%; + height: 30px; + left: 5%; + bottom: 0; + background: none; + z-index: 1; + border-radius: 4px; + box-shadow: 0px 95px 25px rgba(0, 0, 0, 0.2); + -webkit-transform: translateZ(-90px) rotateX(65deg); } + +.reveal[class~=page] .slides > section.stack { + padding: 0; + background: none; } + +.reveal.page .slides > section.past, +.reveal.page-horizontal .slides > section > section.past, +.reveal.page-horizontal-reverse .slides > section > section.future { + -webkit-transform-origin: 0% 0%; + transform-origin: 0% 0%; + -webkit-transform: translate3d(-40%, 0, 0) rotateY(-80deg); + transform: translate3d(-40%, 0, 0) rotateY(-80deg); } + +.reveal.page .slides > section.future, +.reveal.page-horizontal .slides > section > section.future, +.reveal.page-horizontal-reverse .slides > section > section.past { + -webkit-transform-origin: 100% 0%; + transform-origin: 100% 0%; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +.reveal.page-vertical .slides > section > section.past, +.reveal.page-vertical-reverse .slides > section > section.future { + -webkit-transform-origin: 0% 0%; + transform-origin: 0% 0%; + -webkit-transform: translate3d(0, -40%, 0) rotateX(80deg); + transform: translate3d(0, -40%, 0) rotateX(80deg); } + +.reveal.page-vertical .slides > section > section.future, +.reveal.page-vertical-reverse .slides > section > section.past { + -webkit-transform-origin: 0% 100%; + transform-origin: 0% 100%; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } + +/********************************************* + * FADE TRANSITION + *********************************************/ +.reveal .slides section[data-transition~=fade], +.reveal[class~=fade] .slides section:not([data-transition]), +.reveal[class~=fade] .slides > section > section:not([data-transition]) { + -webkit-transform: none; + transform: none; + transition: opacity 0.5s; } \ No newline at end of file diff --git a/openlp/core/display/html/display.js b/openlp/core/display/html/display.js index 6d9284a2c..44ca1374b 100644 --- a/openlp/core/display/html/display.js +++ b/openlp/core/display/html/display.js @@ -63,6 +63,15 @@ var TransitionSpeed = { Slow: 2 }; + +/** + * Transition direction enumeration + */ +var TransitionDirection = { + Horizontal: 0, + Vertical: 1 +}; + /** * Audio state enumeration */ @@ -931,7 +940,19 @@ var Display = { default: new_transition_speed = "default"; } + switch (theme.display_slide_transition_direction) { + case TransitionDirection.Vertical: + new_transition_type += "-vertical"; + break; + case TransitionDirection.Horizontal: + default: + new_transition_type += "-horizontal"; + } + if (theme.display_slide_transition_reverse) { + new_transition_type += "-reverse"; + } } + Display.setTransition(new_transition_type, new_transition_speed); // Set the background var globalBackground = $("#global-background")[0]; diff --git a/openlp/core/lib/json/theme.json b/openlp/core/lib/json/theme.json index 1a6018535..6504478d4 100644 --- a/openlp/core/lib/json/theme.json +++ b/openlp/core/lib/json/theme.json @@ -13,6 +13,8 @@ "slide_transition": false, "slide_transition_type": 0, "slide_transition_speed": 0, + "slide_transition_direction": 0, + "slide_transition_reverse": false, "vertical_align": 0 }, "font": { diff --git a/openlp/core/lib/theme.py b/openlp/core/lib/theme.py index a840a4a3c..5692fea01 100644 --- a/openlp/core/lib/theme.py +++ b/openlp/core/lib/theme.py @@ -203,6 +203,34 @@ class TransitionSpeed(object): return TransitionSpeed.Slow +class TransitionDirection(object): + """ + Type enumeration for transition types. + """ + Horizontal = 0 + Vertical = 1 + + @staticmethod + def to_string(transition_direction): + """ + Return a string representation of a transition type. + """ + if transition_direction == TransitionDirection.Horizontal: + return 'horizontal' + elif transition_direction == TransitionDirection.Vertical: + return 'vertical' + + @staticmethod + def from_string(type_string): + """ + Return a transition type for the given string. + """ + if type_string == 'horizontal': + return TransitionDirection.Horizontal + if type_string == 'vertical': + return TransitionDirection.Vertical + + class HorizontalType(object): """ Type enumeration for horizontal alignment. @@ -254,10 +282,11 @@ class VerticalType(object): return VerticalType.Names.index(align) -BOOLEAN_LIST = ['bold', 'italics', 'override', 'outline', 'shadow', 'slide_transition'] +BOOLEAN_LIST = ['bold', 'italics', 'override', 'outline', 'shadow', 'slide_transition', 'slide_transition_reverse'] INTEGER_LIST = ['size', 'line_adjustment', 'x', 'height', 'y', 'width', 'shadow_size', 'outline_size', - 'horizontal_align', 'vertical_align', 'wrap_style', 'slide_transition_type', 'slide_transition_speed'] + 'horizontal_align', 'vertical_align', 'wrap_style', 'slide_transition_type', 'slide_transition_speed', + 'slide_transition_direction'] class Theme(object): diff --git a/openlp/core/pages/alignment.py b/openlp/core/pages/alignment.py index b25a4e305..ddd9b7b31 100644 --- a/openlp/core/pages/alignment.py +++ b/openlp/core/pages/alignment.py @@ -24,7 +24,7 @@ The :mod:`~openlp.core.pages.alignment` module contains the alignment page used from PyQt5 import QtWidgets from openlp.core.common.i18n import translate -from openlp.core.lib.theme import HorizontalType, VerticalType, TransitionType, TransitionSpeed +from openlp.core.lib.theme import HorizontalType, VerticalType, TransitionType, TransitionSpeed, TransitionDirection from openlp.core.lib.ui import create_valign_selection_widgets from openlp.core.pages import GridLayoutPage from openlp.core.widgets.labels import FormLabel @@ -69,11 +69,21 @@ class AlignmentTransitionsPage(GridLayoutPage): self.layout.addWidget(self.transition_effect_combo_box, 4, 1) self.transition_speed_label = FormLabel(self) self.transition_speed_label.setObjectName('transition_speed_label') - self.layout.addWidget(self.transition_speed_label, 4, 2) + self.layout.addWidget(self.transition_speed_label, 5, 0) self.transition_speed_combo_box = QtWidgets.QComboBox(self) self.transition_speed_combo_box.setObjectName('transition_speed_combo_box') self.transition_speed_combo_box.addItems(['', '', '']) - self.layout.addWidget(self.transition_speed_combo_box, 4, 3) + self.layout.addWidget(self.transition_speed_combo_box, 5, 1) + self.transition_direction_label = FormLabel(self) + self.transition_direction_label.setObjectName('transition_direction_label') + self.layout.addWidget(self.transition_direction_label, 4, 2) + self.transition_direction_combo_box = QtWidgets.QComboBox(self) + self.transition_direction_combo_box.setObjectName('transition_direction_combo_box') + self.transition_direction_combo_box.addItems(['', '']) + self.layout.addWidget(self.transition_direction_combo_box, 4, 3) + self.transition_reverse_check_box = QtWidgets.QCheckBox(self) + self.transition_reverse_check_box.setObjectName('transition_reverse_check_box') + self.layout.addWidget(self.transition_reverse_check_box, 5, 3) # Connect slots self.transitions_enabled_check_box.stateChanged.connect(self._on_transition_enabled_changed) @@ -97,6 +107,12 @@ class AlignmentTransitionsPage(GridLayoutPage): self.transition_speed_combo_box.setItemText(TransitionSpeed.Normal, translate('OpenLP.ThemeWizard', 'Normal')) self.transition_speed_combo_box.setItemText(TransitionSpeed.Fast, translate('OpenLP.ThemeWizard', 'Fast')) self.transition_speed_combo_box.setItemText(TransitionSpeed.Slow, translate('OpenLP.ThemeWizard', 'Slow')) + self.transition_direction_label.setText(translate('OpenLP.ThemeWizard', 'Direction:')) + self.transition_direction_combo_box.setItemText(TransitionDirection.Horizontal, translate('OpenLP.ThemeWizard', + 'Horizontal')) + self.transition_direction_combo_box.setItemText(TransitionDirection.Vertical, translate('OpenLP.ThemeWizard', + 'Vertical')) + self.transition_reverse_check_box.setText(translate('OpenLP.ThemeWizard', 'Reverse')) def _on_transition_enabled_changed(self, value): """ @@ -106,6 +122,9 @@ class AlignmentTransitionsPage(GridLayoutPage): self.transition_effect_combo_box.setEnabled(value) self.transition_speed_label.setEnabled(value) self.transition_speed_combo_box.setEnabled(value) + self.transition_direction_combo_box.setEnabled(value) + self.transition_direction_label.setEnabled(value) + self.transition_reverse_check_box.setEnabled(value) @property def horizontal_align(self): @@ -167,3 +186,24 @@ class AlignmentTransitionsPage(GridLayoutPage): self.transition_speed_combo_box.setCurrentIndex(value) else: raise TypeError('transition_speed must either be a string or an int') + + @property + def transition_direction(self): + return self.transition_direction_combo_box.currentIndex() + + @transition_direction.setter + def transition_direction(self, value): + if isinstance(value, str): + self.transition_direction_combo_box.setCurrentIndex(TransitionDirection.from_string(value)) + elif isinstance(value, int): + self.transition_direction_combo_box.setCurrentIndex(value) + else: + raise TypeError('transition_direction must either be a string or an int') + + @property + def is_transition_reverse_enabled(self): + return self.transition_reverse_check_box.isChecked() + + @is_transition_reverse_enabled.setter + def is_transition_reverse_enabled(self, value): + self.transition_reverse_check_box.setChecked(value) diff --git a/openlp/core/ui/themeform.py b/openlp/core/ui/themeform.py index 5f253851f..689b165b8 100644 --- a/openlp/core/ui/themeform.py +++ b/openlp/core/ui/themeform.py @@ -304,6 +304,8 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties): self.alignment_page.is_transition_enabled = self.theme.display_slide_transition self.alignment_page.transition_type = self.theme.display_slide_transition_type self.alignment_page.transition_speed = self.theme.display_slide_transition_speed + self.alignment_page.transition_direction = self.theme.display_slide_transition_direction + self.alignment_page.is_transition_reverse_enabled = self.theme.display_slide_transition_reverse def set_preview_page_values(self): """ @@ -371,6 +373,8 @@ class ThemeForm(QtWidgets.QWizard, Ui_ThemeWizard, RegistryProperties): self.theme.display_slide_transition = self.alignment_page.is_transition_enabled self.theme.display_slide_transition_type = self.alignment_page.transition_type self.theme.display_slide_transition_speed = self.alignment_page.transition_speed + self.theme.display_slide_transition_direction = self.alignment_page.transition_direction + self.theme.display_slide_transition_reverse = self.alignment_page.is_transition_reverse_enabled def accept(self): """ diff --git a/tests/functional/openlp_core/lib/test_theme.py b/tests/functional/openlp_core/lib/test_theme.py index 7f7d944c3..9d92431ed 100644 --- a/tests/functional/openlp_core/lib/test_theme.py +++ b/tests/functional/openlp_core/lib/test_theme.py @@ -337,4 +337,4 @@ class TestTheme(TestCase): assert 0 == theme.display_vertical_align, 'display_vertical_align should be 0' assert theme.font_footer_bold is False, 'font_footer_bold should be False' assert 'Arial' == theme.font_main_name, 'font_main_name should be "Arial"' - assert 51 == len(theme.__dict__), 'The theme should have 51 attributes' + assert 53 == len(theme.__dict__), 'The theme should have 53 attributes' diff --git a/tests/js/test_display.js b/tests/js/test_display.js index 748ad9b6e..ce0298e37 100644 --- a/tests/js/test_display.js +++ b/tests/js/test_display.js @@ -184,7 +184,7 @@ describe("Transitions", function () { Display.setTheme(theme); - expect(Display.setTransition).toHaveBeenCalledWith("slide", "fast"); + expect(Display.setTransition).toHaveBeenCalledWith("slide-horizontal", "fast"); }); it("should have not enabled transitions when init() with no transitions and setTheme is run", function () { @@ -201,6 +201,22 @@ describe("Transitions", function () { expect(Display.setTransition).toHaveBeenCalledWith("none", "default"); }); + it("should have enabled transitions in the correct direction", function () { + spyOn(Display, "setTransition"); + Display._doTransitions = true; + var theme = { + "display_slide_transition": true, + "display_slide_transition_type": TransitionType.Convex, + "display_slide_transition_speed": TransitionSpeed.Slow, + "display_slide_transition_direction": TransitionDirection.Vertical, + "display_slide_transition_reverse": true, + } + + Display.setTheme(theme); + + expect(Display.setTransition).toHaveBeenCalledWith("convex-vertical-reverse", "slow"); + }); + }); describe("Display.alert", function () { diff --git a/tests/openlp_core/pages/test_alignment.py b/tests/openlp_core/pages/test_alignment.py index 2a317d2a0..557c2c745 100644 --- a/tests/openlp_core/pages/test_alignment.py +++ b/tests/openlp_core/pages/test_alignment.py @@ -26,7 +26,7 @@ from unittest.mock import MagicMock import pytest -from openlp.core.lib.theme import HorizontalType, VerticalType, TransitionType, TransitionSpeed +from openlp.core.lib.theme import HorizontalType, VerticalType, TransitionType, TransitionSpeed, TransitionDirection from openlp.core.pages.alignment import AlignmentTransitionsPage from tests.helpers.testmixin import TestMixin @@ -66,6 +66,8 @@ class TestAlignmentTransitionsPage(TestCase, TestMixin): assert page.transition_effect_combo_box.isEnabled() assert page.transition_speed_label.isEnabled() assert page.transition_speed_combo_box.isEnabled() + assert page.transition_direction_combo_box.isEnabled() + assert page.transition_reverse_check_box.isEnabled() def test_get_horizontal_align(self): """ @@ -256,7 +258,7 @@ class TestAlignmentTransitionsPage(TestCase, TestMixin): """ Test the transition_speed getter """ - # GIVEN: A AlignmentTransitionsPage instance with the combobox set to index 1 + # GIVEN: A AlignmentTransitionsPage instance with the combobox set to index 0 page = AlignmentTransitionsPage() page.transition_speed_combo_box.setCurrentIndex(0) @@ -303,3 +305,82 @@ class TestAlignmentTransitionsPage(TestCase, TestMixin): # THEN: An exception is raised with pytest.raises(TypeError, match='transition_speed must either be a string or an int'): page.transition_speed = [] + + def test_get_transition_direction(self): + """ + Test the transition_direction getter + """ + # GIVEN: A AlignmentTransitionsPage instance with the combobox set to index 0 + page = AlignmentTransitionsPage() + page.transition_direction_combo_box.setCurrentIndex(0) + + # WHEN: The property is accessed + result = page.transition_direction + + # THEN: The result should be correct + assert result == TransitionDirection.Horizontal + + def test_set_transition_direction_int(self): + """ + Test the transition_direction setter with an int + """ + # GIVEN: A AlignmentTransitionsPage instance + page = AlignmentTransitionsPage() + + # WHEN: The property is set + page.transition_direction = TransitionDirection.Horizontal + + # THEN: The combobox should be correct + assert page.transition_direction_combo_box.currentIndex() == 0 + + def test_set_transition_direction_str(self): + """ + Test the transition_direction setter with a str + """ + # GIVEN: A AlignmentTransitionsPage instance + page = AlignmentTransitionsPage() + + # WHEN: The property is set + page.transition_direction = TransitionDirection.to_string(TransitionDirection.Vertical) + + # THEN: The combobox should be correct + assert page.transition_direction_combo_box.currentIndex() == 1 + + def test_set_transition_direction_exception(self): + """ + Test the transition_direction setter with something other than a str or int + """ + # GIVEN: A AlignmentTransitionsPage instance + page = AlignmentTransitionsPage() + + # WHEN: The property is set + # THEN: An exception is raised + with pytest.raises(TypeError, match='transition_direction must either be a string or an int'): + page.transition_direction = [] + + def test_on_transition_reverse_getter(self): + """ + Test the is_transition_reverse_enabled getter + """ + # GIVEN: And instance of AlignmentTransitionsPage and transition_reverse checked + page = AlignmentTransitionsPage() + page.transition_reverse_check_box.setChecked(True) + + # WHEN: The property is accessed + result = page.is_transition_reverse_enabled + + # THEN: The result should be correct + assert result is True + + def test_on_transition_reverse_setter(self): + """ + Test the is_transition_reverse_enabled setter + """ + # GIVEN: And instance of AlignmentTransitionsPage and transition_reverse checked + page = AlignmentTransitionsPage() + + # WHEN: The property is set + page.is_transition_reverse_enabled = True + + # THEN: The checkbox should be correct + assert page.transition_reverse_check_box.isChecked() is True