← Back to team overview

openlp-core team mailing list archive

[Merge] lp:~googol/openlp/transitions into lp:openlp

 

Andreas Preikschat has proposed merging lp:~googol/openlp/transitions into lp:openlp.

Requested reviews:
  Andreas Preikschat (googol)
Related bugs:
  Bug #1147307 in OpenLP: "Transtion + fast slide changes + ESC causes screen to open again"
  https://bugs.launchpad.net/openlp/+bug/1147307

For more details, see:
https://code.launchpad.net/~googol/openlp/transitions/+merge/151808

Hello,

- use html5 for transitions
- added test *cough* 
- fixed bug #1147307 (Transtion + fast slide changes + ESC causes screen to open again)

Details:
Duration for fading: 400ms
When fading out/-in the lowest opacity is 0.2 because we don't waste time with nothing (really visible) on the screen.

Test on XP:
It should work on windows as well (I tested 2.0.1):
1) Start OpenLP 2.0.1 (the build exe)
2) Drag&drop this file to the maindisplay: http://pastebin.com/pA9a9Mex

Result: fading works, so the version packaged with 2.0.1 seems to support these features.

General Test:
Tested with outline and shadow on my arch box.

Further thoughts:
In the future we can offer two things to the user:
a) Define the fading duration.
b) Define the "overlapping" time (lowest opacity ever reached).
-- 
https://code.launchpad.net/~googol/openlp/transitions/+merge/151808
Your team OpenLP Core is subscribed to branch lp:openlp.
=== modified file 'openlp/core/lib/htmlbuilder.py'
--- openlp/core/lib/htmlbuilder.py	2013-02-02 20:54:34 +0000
+++ openlp/core/lib/htmlbuilder.py	2013-03-05 17:18:26 +0000
@@ -127,7 +127,7 @@
         document.getElementById('footer').innerHTML = footertext;
     }
 
-    function show_text(newtext){
+    function show_text(new_text){
         var match = /-webkit-text-fill-color:[^;\"]+/gi;
         if(timer != null)
             clearTimeout(timer);
@@ -142,23 +142,19 @@
             if(outline != null)
                 txt = outline;
             if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){
-                newtext = newtext.replace(/(\s|&nbsp;)+(?![^<]*>)/g,
+                new_text = new_text.replace(/(\s|&nbsp;)+(?![^<]*>)/g,
                     function(match) {
                         return '</span>' + match + '<span>';
                     });
-                newtext = '<span>' + newtext + '</span>';
+                new_text = '<span>' + new_text + '</span>';
             }
         }
-        text_fade('lyricsmain', newtext);
-        text_fade('lyricsoutline', newtext);
-        text_fade('lyricsshadow', newtext.replace(match, ''));
-        if(text_opacity() == 1) return;
-        timer = setTimeout(function(){
-            show_text(newtext);
-        }, 100);
+        text_fade('lyricsmain', new_text);
+        text_fade('lyricsoutline', new_text);
+        text_fade('lyricsshadow', new_text.replace(match, ''));
     }
 
-    function text_fade(id, newtext){
+    function text_fade(id, new_text){
         /*
         Using -webkit-transition: opacity 1s linear; would have been preferred
         but it isn't currently quick enough when animating multiple layers of
@@ -171,28 +167,28 @@
         var text = document.getElementById(id);
         if(text == null) return;
         if(!transition){
-            text.innerHTML = newtext;
+            text.innerHTML = new_text;
             return;
         }
-        if(newtext == text.innerHTML){
-            text.style.opacity = parseFloat(text.style.opacity) + 0.3;
-            if(text.style.opacity > 0.7)
-                text.style.opacity = 1;
-        } else {
-            text.style.opacity = parseFloat(text.style.opacity) - 0.3;
-            if(text.style.opacity <= 0.1){
-                text.innerHTML = newtext;
-            }
-        }
-    }
-
-    function text_opacity(){
-        var text = document.getElementById('lyricsmain');
-        return getComputedStyle(text, '').opacity;
-    }
-
-    function show_text_complete(){
-        return (text_opacity() == 1);
+        // Fade text out. 0.2 to minimize the time "nothing" is shown on the screen.
+        text.style.opacity = '0.2';
+        // Fade new text in after the old text has finished fading out.
+        timer = window.setTimeout(function(){_show_text(text, new_text)}, 400);
+    }
+
+    function _show_text(text, new_text) {
+        /*
+        Helper function to show the new_text delayed.
+        */
+        text.innerHTML = new_text;
+        text.style.opacity = '1';
+        // Wait until the text is completely visible. We want to save the timer id, to be able to call
+        // clearTimeout(timer) when the text has changed before finishing fading.
+        timer = window.setTimeout(function(){timer = null;}, 400);
+    }
+
+    function show_text_completed(){
+        return (timer == null);
     }
 </script>
 </head>
@@ -336,6 +332,7 @@
 .lyricscell {
     display: table-cell;
     word-wrap: break-word;
+    -webkit-transition: opacity 0.4s ease;
     %s
 }
 .lyricsmain {

=== modified file 'openlp/core/ui/maindisplay.py'
--- openlp/core/ui/maindisplay.py	2013-02-14 21:31:17 +0000
+++ openlp/core/ui/maindisplay.py	2013-03-05 17:18:26 +0000
@@ -347,13 +347,14 @@
         Generates a preview of the image displayed.
         """
         log.debug(u'preview for %s', self.isLive)
+        was_visible = self.isVisible()
         self.application.process_events()
         # We must have a service item to preview.
         if self.isLive and hasattr(self, u'serviceItem'):
             # Wait for the fade to finish before geting the preview.
             # Important otherwise preview will have incorrect text if at all!
             if self.serviceItem.themedata and self.serviceItem.themedata.display_slide_transition:
-                while self.frame.evaluateJavaScript(u'show_text_complete()') == u'false':
+                while not self.frame.evaluateJavaScript(u'show_text_completed()'):
                     self.application.process_events()
         # Wait for the webview to update before getting the preview.
         # Important otherwise first preview will miss the background !
@@ -363,7 +364,8 @@
         if self.isLive:
             if self.hideMode:
                 self.hide_display(self.hideMode)
-            else:
+            # Only continue if the visibility wasn't changed during method call.
+            elif was_visible == self.isVisible():
                 # Single screen active
                 if self.screens.display_count == 1:
                     # Only make visible if setting enabled.

=== modified file 'tests/functional/openlp_core_lib/test_lib.py'
--- tests/functional/openlp_core_lib/test_lib.py	2013-02-10 18:59:00 +0000
+++ tests/functional/openlp_core_lib/test_lib.py	2013-03-05 17:18:26 +0000
@@ -7,7 +7,7 @@
 from mock import MagicMock, patch
 
 from openlp.core.lib import str_to_bool, translate, check_directory_exists, get_text_file_string, build_icon, \
-    image_to_byte, check_item_selected, validate_thumb, create_separated_list
+    image_to_byte, check_item_selected, validate_thumb, create_separated_list, expand_tags
 
 class TestLib(TestCase):
 
@@ -299,6 +299,45 @@
             MockedQtGui.QMessageBox.information.assert_called_with(u'parent', u'mocked translate', 'message')
             assert not result, u'The result should be False'
 
+    def expand_tags_test(self):
+        """
+        Test the expand_tags() method.
+        """
+        with patch(u'openlp.core.lib.FormattingTags.get_html_tags') as mocked_get_tags:
+            # GIVEN: Mocked get_html_tags() method.
+            mocked_get_tags.return_value = [
+                {
+                    u'desc': u'Black',
+                    u'start tag': u'{b}',
+                    u'start html': u'<span style="-webkit-text-fill-color:black">',
+                    u'end tag': u'{/b}', u'end html': u'</span>', u'protected': True,
+                    u'temporary': False
+                },
+                {
+                    u'desc': u'Yellow',
+                    u'start tag': u'{y}',
+                    u'start html': u'<span style="-webkit-text-fill-color:yellow">',
+                    u'end tag': u'{/y}', u'end html': u'</span>', u'protected': True,
+                    u'temporary': False
+                },
+                {
+                    u'desc': u'Green',
+                    u'start tag': u'{g}',
+                    u'start html': u'<span style="-webkit-text-fill-color:green">',
+                    u'end tag': u'{/g}', u'end html': u'</span>', u'protected': True,
+                    u'temporary': False
+                }
+            ]
+            string_to_pass = u'{b}black{/b}{y}yellow{/y}'
+            wanted_string = u'<span style="-webkit-text-fill-color:black">black</span>' + \
+                '<span style="-webkit-text-fill-color:yellow">yellow</span>'
+
+            # WHEN: Replace the tags.
+            result_string = expand_tags(string_to_pass)
+
+            # THEN: The strings should be identical.
+            assert result_string == wanted_string, u'The strings should be identical.'
+
     def validate_thumb_file_does_not_exist_test(self):
         """
         Test the validate_thumb() function when the thumbnail does not exist


Follow ups