← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~oliwee/openlp/newtransition into lp:openlp

 

Oliver Wieland has proposed merging lp:~oliwee/openlp/newtransition into lp:openlp.

Requested reviews:
  OpenLP Core (openlp-core)

For more details, see:
https://code.launchpad.net/~oliwee/openlp/newtransition/+merge/248188

Added a second type of transition, which is more a crossfade than a fade-out-then-fade-in.
Added / adapted tests for htmlbuilder to match the new html code
-- 
Your team OpenLP Core is requested to review the proposed merge of lp:~oliwee/openlp/newtransition into lp:openlp.
=== modified file 'openlp/core/lib/htmlbuilder.py'
--- openlp/core/lib/htmlbuilder.py	2015-01-18 13:39:21 +0000
+++ openlp/core/lib/htmlbuilder.py	2015-01-31 10:00:29 +0000
@@ -117,6 +117,9 @@
         .lyricsmain {
              -webkit-text-stroke: 0.125em #000000; -webkit-text-fill-color: #FFFFFF;  text-shadow: #000000 5px 5px;
         }
+        .lyricstext {
+            -webkit-transition: opacity 0.4s ease;
+        }
 
         sup {
             font-size: 0.6em;
@@ -128,6 +131,7 @@
         <script>
             var timer = null;
             var transition = false;
+            var transition_type = '0';
 
             function show_video(state, path, volume, loop, variable_value){
                 // Sometimes  video.currentTime stops slightly short of video.duration and video.ended is intermittent!
@@ -342,16 +346,34 @@
                 /*
                 Show the text.
                 */
-                var text = document.getElementById(id);
-                if(text == null) return;
+                var text1 = document.getElementById(id).childNodes[0];
+                var text2 = document.getElementById(id).childNodes[1];
+                if(text1 == null) return;
+                if(text2 == null) return;
                 if(!transition){
-                    text.innerHTML = new_text;
+                    text1.innerHTML = new_text;
+                    text2.innerHTML = new_text;
                     return;
                 }
-                // Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
-                text.style.opacity = '0.1';
-                // Fade new text in after the old text has finished fading out.
-                timer = window.setTimeout(function(){_show_text(text, new_text)}, 400);
+                if(transition_type == 0){
+                    // Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
+                    text1.style.opacity = '0.1';
+                    // Fade new text in after the old text has finished fading out.
+                    timer = window.setTimeout(function(){_show_text(text1, new_text)}, 400);
+                }else{
+                    // Toggle visible text element by fading out / in
+                    if (text1.style.opacity == '1'){
+                        text2.innerHTML = new_text;
+                        text1.style.opacity = '0';
+                        text2.style.opacity = '1';
+                    }
+                    else{
+                        text1.innerHTML = new_text;
+                        text2.style.opacity = '0';
+                        text1.style.opacity = '1';
+                    }
+                    timer = window.setTimeout(function(){timer = null;}, 400);
+                }
             }
 
             function _show_text(text, new_text) {
@@ -381,7 +403,7 @@
 
             <div id="alert" style="visibility:hidden"></div>
 
-        <div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"></div></div>
+        <div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"><div id="lyricstext1" class="lyricstext" style="opacity:1;"></div><div id="lyricstext2" class="lyricstext" style="opacity:0;position:absolute;top:0px;left:0px;"></div></div></div>
         <div id="footer" class="footer"></div>
         <div id="black" class="size"></div>
         </body>
@@ -448,6 +470,7 @@
 <script>
     var timer = null;
     var transition = %s;
+    var transition_type = %s;
     %s
 
     function show_image(src){
@@ -474,6 +497,7 @@
         }
         document.getElementById('black').style.display = black;
         document.getElementById('lyricsmain').style.visibility = lyrics;
+        document.getElementById('lyricsmain2').style.visibility = lyrics;
         document.getElementById('image').style.visibility = lyrics;
         document.getElementById('footer').style.visibility = lyrics;
     }
@@ -501,23 +525,51 @@
                 new_text = '<span>' + new_text + '</span>';
             }
         }
-        text_fade('lyricsmain', new_text);
+        txt = document.getElementById('lyricsmain2');
+        if(window.getComputedStyle(txt).textAlign == 'justify'){
+            if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){
+                new_text = new_text.replace(/(\s|&nbsp;)+(?![^<]*>)/g,
+                    function(match) {
+                        return '</span>' + match + '<span>';
+                    });
+                new_text = '<span>' + new_text + '</span>';
+            }
+        }
+        text_fade('lyricsmain', 'lyricsmain2', new_text);
     }
 
-    function text_fade(id, new_text){
+    function text_fade(id, id2, new_text){
         /*
         Show the text.
         */
-        var text = document.getElementById(id);
-        if(text == null) return;
+        var text1 = document.getElementById(id);
+        var text2 = document.getElementById(id2);
+        if(text1 == null) return;
+        if(text2 == null) return;
         if(!transition){
-            text.innerHTML = new_text;
+            text1.innerHTML = new_text;
+            text2.innerHTML = new_text;
             return;
         }
-        // Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
-        text.style.opacity = '0.1';
-        // Fade new text in after the old text has finished fading out.
-        timer = window.setTimeout(function(){_show_text(text, new_text)}, 400);
+        if(transition_type == 0){
+            // Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
+            text1.style.opacity = '0.1';
+            // Fade new text in after the old text has finished fading out.
+            timer = window.setTimeout(function(){_show_text(text1, new_text)}, 400);
+        }else{
+            // Toggle visible text element by fading out / in
+            if (text1.style.opacity == '1'){
+                text2.innerHTML = new_text;
+                text1.style.opacity = '0';
+                text2.style.opacity = '1';
+            }
+            else{
+                text1.innerHTML = new_text;
+                text2.style.opacity = '0';
+                text1.style.opacity = '1';
+            }
+            timer = window.setTimeout(function(){timer = null;}, 400);
+        }
     }
 
     function _show_text(text, new_text) {
@@ -541,6 +593,7 @@
 <img id="image" class="size" %s />
 %s
 <div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"></div></div>
+<div class="lyricstable"><div id="lyricsmain2" style="opacity:0" class="lyricscell lyricsmain"></div></div>
 <div id="footer" class="footer"></div>
 <div id="black" class="size"></div>
 </body>
@@ -587,6 +640,7 @@
         build_footer_css(item, height),
         build_lyrics_css(item),
         'true' if theme_data and theme_data.display_slide_transition and is_live else 'false',
+        get_transition_type(item),
         js_additions,
         bgimage_src,
         image_src,
@@ -754,3 +808,15 @@
     lyrics_html = style % (item.footer.x(), bottom, item.footer.width(),
                            theme.font_footer_name, theme.font_footer_size, theme.font_footer_color, whitespace)
     return lyrics_html
+
+def get_transition_type(item):
+    """
+    Returns the transition type of the theme
+    
+    :param item: Service Item to be processed.
+    """
+    theme= item.theme_data
+    if not theme:
+        return '0'
+    
+    return theme.display_slide_transition_type
\ No newline at end of file

=== modified file 'openlp/core/lib/json/theme.json'
--- openlp/core/lib/json/theme.json	2013-10-18 18:10:47 +0000
+++ openlp/core/lib/json/theme.json	2015-01-31 10:00:29 +0000
@@ -11,6 +11,7 @@
     "display" :{
         "horizontal_align": 0,
         "slide_transition": false,
+        "slide_transition_type": 0,
         "vertical_align": 0
     },
     "font": {

=== modified file 'openlp/core/lib/theme.py'
--- openlp/core/lib/theme.py	2015-01-18 13:39:21 +0000
+++ openlp/core/lib/theme.py	2015-01-31 10:00:29 +0000
@@ -140,6 +140,33 @@
     Names = ['top', 'middle', 'bottom']
 
 
+class TransitionType(object):
+    """
+    Type enumeration for backgrounds.
+    """
+    Fadeout_fadein = 0
+    Crossfade = 1
+
+    @staticmethod
+    def to_string(transition_type):
+        """
+        Return a string representation of a transition type.
+        """
+        if transition_type == TransitionType.Fadeout_fadein:
+            return 'Fade Out - Fade In'
+        elif transition_type == TransitionType.Crossfade:
+            return 'Crossfade'
+
+    @staticmethod
+    def from_string(type_string):
+        """
+        Return a transition type for the given string.
+        """
+        if type_string == 'Fade Out - Fade In':
+            return TransitionType.Fadeout_fadein
+        elif type_string == 'Crossfade':
+            return TransitionType.Crossfade
+
 BOOLEAN_LIST = ['bold', 'italics', 'override', 'outline', 'shadow', 'slide_transition']
 
 INTEGER_LIST = ['size', 'line_adjustment', 'x', 'height', 'y', 'width', 'shadow_size', 'outline_size',
@@ -318,13 +345,14 @@
         element.appendChild(value)
         background.appendChild(element)
 
-    def add_display(self, horizontal, vertical, transition):
+    def add_display(self, horizontal, vertical, transition, transition_type):
         """
         Add a Display options.
 
         :param horizontal: The horizontal alignment of the text.
         :param vertical: The vertical alignment of the text.
         :param transition: Whether the slide transition is active.
+        _param transition_type: Type of the slide transition.
         """
         background = self.theme_xml.createElement('display')
         self.theme.appendChild(background)
@@ -343,6 +371,11 @@
         value = self.theme_xml.createTextNode(str(transition))
         element.appendChild(value)
         background.appendChild(element)
+        # Slide Transition Type
+        element = self.theme_xml.createElement('slideTransitionType')
+        value = self.theme_xml.createTextNode(str(transition_type))
+        element.appendChild(value)
+        background.appendChild(element)
 
     def child_element(self, element, tag, value):
         """
@@ -555,5 +588,6 @@
         self.add_display(
             self.display_horizontal_align,
             self.display_vertical_align,
-            self.display_slide_transition
+            self.display_slide_transition,
+            self.display_slide_transition_type
         )

=== modified file 'openlp/core/ui/themeform.py'
--- openlp/core/ui/themeform.py	2015-01-18 13:39:21 +0000
+++ openlp/core/ui/themeform.py	2015-01-31 10:00:29 +0000
@@ -28,7 +28,7 @@
 from PyQt4 import QtCore, QtGui
 
 from openlp.core.common import Registry, RegistryProperties, UiStrings, translate
-from openlp.core.lib.theme import BackgroundType, BackgroundGradientType
+from openlp.core.lib.theme import BackgroundType, BackgroundGradientType, TransitionType
 from openlp.core.lib.ui import critical_error_message_box
 from openlp.core.ui import ThemeLayoutForm
 from openlp.core.utils import get_images_filter, is_not_image_file
@@ -88,6 +88,7 @@
         self.main_font_combo_box.activated.connect(self.calculate_lines)
         self.footer_font_combo_box.activated.connect(self.update_theme)
         self.footer_size_spin_box.valueChanged.connect(self.update_theme)
+        self.transitions_combo_box.currentIndexChanged.connect(self.on_transitions_combo_box_current_index_changed)
 
     def set_defaults(self):
         """
@@ -134,6 +135,7 @@
         self.background_page.registerField('horizontal', self.horizontal_combo_box)
         self.background_page.registerField('vertical', self.vertical_combo_box)
         self.background_page.registerField('slide_transition', self.transitions_check_box)
+        self.background_page.registerField('slide_transition_type', self.transitions_combo_box)
         self.background_page.registerField('name', self.theme_name_edit)
 
     def calculate_lines(self):
@@ -366,6 +368,7 @@
         self.setField('horizontal', self.theme.display_horizontal_align)
         self.setField('vertical', self.theme.display_vertical_align)
         self.setField('slide_transition', self.theme.display_slide_transition)
+        self.setField('slide_transition_type', self.theme.display_slide_transition_type)
 
     def set_preview_page_values(self):
         """
@@ -464,6 +467,14 @@
         """
         self.theme.font_footer_color = color
 
+    def on_transitions_combo_box_current_index_changed(self, index):
+        """
+        Transition style Combo box has changed.
+        """
+        # do not allow updates when screen is building for the first time.
+        if self.update_theme_allowed:
+            self.theme.transition_type = TransitionType.to_string(index)
+
     def update_theme(self):
         """
         Update the theme object from the UI for fields not already updated
@@ -496,6 +507,7 @@
         self.theme.display_horizontal_align = self.horizontal_combo_box.currentIndex()
         self.theme.display_vertical_align = self.vertical_combo_box.currentIndex()
         self.theme.display_slide_transition = self.field('slide_transition')
+        self.theme.display_slide_transition_type = self.field('slide_transition_type')
 
     def accept(self):
         """

=== modified file 'openlp/core/ui/themewizard.py'
--- openlp/core/ui/themewizard.py	2015-01-18 13:39:21 +0000
+++ openlp/core/ui/themewizard.py	2015-01-31 10:00:29 +0000
@@ -26,7 +26,7 @@
 
 from openlp.core.common import UiStrings, translate, is_macosx
 from openlp.core.lib import build_icon, ColorButton
-from openlp.core.lib.theme import HorizontalType, BackgroundType, BackgroundGradientType
+from openlp.core.lib.theme import HorizontalType, BackgroundType, BackgroundGradientType, TransitionType
 from openlp.core.lib.ui import add_welcome_page, create_valign_selection_widgets
 
 
@@ -257,9 +257,17 @@
         self.alignment_layout.addRow(self.vertical_label, self.vertical_combo_box)
         self.transitions_label = QtGui.QLabel(self.alignment_page)
         self.transitions_label.setObjectName('transitions_label')
+        self.transitions_properties_layout = QtGui.QHBoxLayout()
+        self.transitions_properties_layout.setObjectName('transitions_properties_layout')
         self.transitions_check_box = QtGui.QCheckBox(self.alignment_page)
         self.transitions_check_box.setObjectName('transitions_check_box')
-        self.alignment_layout.addRow(self.transitions_label, self.transitions_check_box)
+        self.transitions_properties_layout.addWidget(self.transitions_check_box)
+        self.transitions_properties_layout.addSpacing(20)
+        self.transitions_combo_box = QtGui.QComboBox(self.alignment_page)
+        self.transitions_combo_box.addItems(['', ''])
+        self.transitions_combo_box.setObjectName('transitions_combo_box')
+        self.transitions_properties_layout.addWidget(self.transitions_combo_box)
+        self.alignment_layout.addRow(self.transitions_label, self.transitions_properties_layout)
         self.alignment_layout.setItem(3, QtGui.QFormLayout.LabelRole, self.spacer)
         theme_wizard.addPage(self.alignment_page)
         # Area Position Page
@@ -458,6 +466,10 @@
         self.horizontal_combo_box.setItemText(HorizontalType.Center, translate('OpenLP.ThemeWizard', 'Center'))
         self.horizontal_combo_box.setItemText(HorizontalType.Justify, translate('OpenLP.ThemeWizard', 'Justify'))
         self.transitions_label.setText(translate('OpenLP.ThemeWizard', 'Transitions:'))
+        self.transitions_combo_box.setItemText(TransitionType.Fadeout_fadein,
+                                              translate('OpenLP.ThemeWizard', 'Fade out - Fade in'))
+        self.transitions_combo_box.setItemText(TransitionType.Crossfade,
+                                              translate('OpenLP.ThemeWizard', 'Crossfade'))
         self.area_position_page.setTitle(translate('OpenLP.ThemeWizard', 'Output Area Locations'))
         self.area_position_page.setSubTitle(translate('OpenLP.ThemeWizard', 'Allows you to change and move the'
                                                       ' Main and Footer areas.'))

=== modified file 'tests/functional/openlp_core_lib/test_htmlbuilder.py'
--- tests/functional/openlp_core_lib/test_htmlbuilder.py	2014-07-24 21:57:16 +0000
+++ tests/functional/openlp_core_lib/test_htmlbuilder.py	2015-01-31 10:00:29 +0000
@@ -8,7 +8,7 @@
 
 from openlp.core.common import Settings
 from openlp.core.lib.htmlbuilder import build_html, build_background_css, build_lyrics_css, build_lyrics_outline_css, \
-    build_lyrics_format_css, build_footer_css
+    build_lyrics_format_css, build_footer_css, get_transition_type
 from openlp.core.lib.theme import HorizontalType, VerticalType
 from tests.functional import MagicMock, patch
 from tests.helpers.testmixin import TestMixin
@@ -65,6 +65,7 @@
 <script>
     var timer = null;
     var transition = false;
+    var transition_type = 0;
     plugin JS
 
     function show_image(src){
@@ -91,6 +92,7 @@
         }
         document.getElementById('black').style.display = black;
         document.getElementById('lyricsmain').style.visibility = lyrics;
+        document.getElementById('lyricsmain2').style.visibility = lyrics;
         document.getElementById('image').style.visibility = lyrics;
         document.getElementById('footer').style.visibility = lyrics;
     }
@@ -100,7 +102,7 @@
     }
 
     function show_text(new_text){
-        var match = /-webkit-text-fill-color:[^;"]+/gi;
+        var match = /-webkit-text-fill-color:[^;\"]+/gi;
         if(timer != null)
             clearTimeout(timer);
         /*
@@ -118,23 +120,51 @@
                 new_text = '<span>' + new_text + '</span>';
             }
         }
-        text_fade('lyricsmain', new_text);
+        txt = document.getElementById('lyricsmain2');
+        if(window.getComputedStyle(txt).textAlign == 'justify'){
+            if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){
+                new_text = new_text.replace(/(\s|&nbsp;)+(?![^<]*>)/g,
+                    function(match) {
+                        return '</span>' + match + '<span>';
+                    });
+                new_text = '<span>' + new_text + '</span>';
+            }
+        }
+        text_fade('lyricsmain', 'lyricsmain2', new_text);
     }
 
-    function text_fade(id, new_text){
+    function text_fade(id, id2, new_text){
         /*
         Show the text.
         */
-        var text = document.getElementById(id);
-        if(text == null) return;
+        var text1 = document.getElementById(id);
+        var text2 = document.getElementById(id2);
+        if(text1 == null) return;
+        if(text2 == null) return;
         if(!transition){
-            text.innerHTML = new_text;
+            text1.innerHTML = new_text;
+            text2.innerHTML = new_text;
             return;
         }
-        // Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
-        text.style.opacity = '0.1';
-        // Fade new text in after the old text has finished fading out.
-        timer = window.setTimeout(function(){_show_text(text, new_text)}, 400);
+        if(transition_type == 0){
+            // Fade text out. 0.1 to minimize the time "nothing" is shown on the screen.
+            text1.style.opacity = '0.1';
+            // Fade new text in after the old text has finished fading out.
+            timer = window.setTimeout(function(){_show_text(text1, new_text)}, 400);
+        }else{
+            // Toggle visible text element by fading out / in
+            if (text1.style.opacity == '1'){
+                text2.innerHTML = new_text;
+                text1.style.opacity = '0';
+                text2.style.opacity = '1';
+            }
+            else{
+                text1.innerHTML = new_text;
+                text2.style.opacity = '0';
+                text1.style.opacity = '1';
+            }
+            timer = window.setTimeout(function(){timer = null;}, 400);
+        }
     }
 
     function _show_text(text, new_text) {
@@ -158,6 +188,7 @@
 <img id="image" class="size" style="display:none;" />
 plugin HTML
 <div class="lyricstable"><div id="lyricsmain" style="opacity:1" class="lyricscell lyricsmain"></div></div>
+<div class="lyricstable"><div id="lyricsmain2" style="opacity:0" class="lyricscell lyricsmain"></div></div>
 <div id="footer" class="footer"></div>
 <div id="black" class="size"></div>
 </body>
@@ -230,6 +261,7 @@
             # Mocked arguments.
             item = MagicMock()
             item.bg_image_bytes = None
+            item.theme_data.display_slide_transition_type = 0
             screen = MagicMock()
             is_live = False
             background = None
@@ -238,6 +270,7 @@
             plugin.get_display_javascript.return_value = 'plugin JS'
             plugin.get_display_html.return_value = 'plugin HTML'
             plugins = [plugin]
+            self.maxDiff = None
 
             # WHEN: Create the html.
             html = build_html(item, screen, is_live, background, plugins=plugins)
@@ -358,3 +391,18 @@
 
         # THEN: Footer should wrap
         self.assertEqual(FOOTER_CSS_WRAP, css, 'The footer strings should be equal.')
+
+    def get_transition_type_test(self):
+        """
+        Test the get_transition_type() function
+        """
+        # GIVEN: Create a theme.
+        item = MagicMock()
+        item.theme_data.display_slide_transition_type = 1
+        
+        #WHEN: get transition type
+        transition_type = get_transition_type(item);
+        
+        #THEN: transition type should be 1
+        self.assertEqual(1, transition_type, 'The transition type should be 1.');
+        
\ No newline at end of file


Follow ups