- use html5 for transitions

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

bzr-revno: 2200
Fixes: https://launchpad.net/bugs/1147307
This commit is contained in:
Andreas Preikschat 2013-03-06 21:04:12 +01:00
commit 88fb52ffba
3 changed files with 69 additions and 37 deletions

View File

@ -127,7 +127,7 @@ sup {
document.getElementById('footer').innerHTML = footertext; document.getElementById('footer').innerHTML = footertext;
} }
function show_text(newtext){ function show_text(new_text){
var match = /-webkit-text-fill-color:[^;\"]+/gi; var match = /-webkit-text-fill-color:[^;\"]+/gi;
if(timer != null) if(timer != null)
clearTimeout(timer); clearTimeout(timer);
@ -142,57 +142,47 @@ sup {
if(outline != null) if(outline != null)
txt = outline; txt = outline;
if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){ if(window.getComputedStyle(txt).webkitTextStrokeWidth != '0px'){
newtext = newtext.replace(/(\s|&nbsp;)+(?![^<]*>)/g, new_text = new_text.replace(/(\s|&nbsp;)+(?![^<]*>)/g,
function(match) { function(match) {
return '</span>' + match + '<span>'; return '</span>' + match + '<span>';
}); });
newtext = '<span>' + newtext + '</span>'; new_text = '<span>' + new_text + '</span>';
} }
} }
text_fade('lyricsmain', newtext); text_fade('lyricsmain', new_text);
text_fade('lyricsoutline', newtext); text_fade('lyricsoutline', new_text);
text_fade('lyricsshadow', newtext.replace(match, '')); text_fade('lyricsshadow', new_text.replace(match, ''));
if(text_opacity() == 1) return;
timer = setTimeout(function(){
show_text(newtext);
}, 100);
} }
function text_fade(id, newtext){ function text_fade(id, new_text){
/* /*
Using -webkit-transition: opacity 1s linear; would have been preferred Show the text.
but it isn't currently quick enough when animating multiple layers of
large areas of large text. Therefore do it manually as best we can.
Hopefully in the future we can revisit and do more interesting
transitions using -webkit-transition and -webkit-transform.
However we need to ensure interrupted transitions (quickly change 2
slides) still looks pretty and is zippy.
*/ */
var text = document.getElementById(id); var text = document.getElementById(id);
if(text == null) return; if(text == null) return;
if(!transition){ if(!transition){
text.innerHTML = newtext; text.innerHTML = new_text;
return; return;
} }
if(newtext == text.innerHTML){ // Fade text out. 0.2 to minimize the time "nothing" is shown on the screen.
text.style.opacity = parseFloat(text.style.opacity) + 0.3; text.style.opacity = '0.2';
if(text.style.opacity > 0.7) // Fade new text in after the old text has finished fading out.
text.style.opacity = 1; timer = window.setTimeout(function(){_show_text(text, new_text)}, 400);
} else {
text.style.opacity = parseFloat(text.style.opacity) - 0.3;
if(text.style.opacity <= 0.1){
text.innerHTML = newtext;
}
}
} }
function text_opacity(){ function _show_text(text, new_text) {
var text = document.getElementById('lyricsmain'); /*
return getComputedStyle(text, '').opacity; 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_complete(){ function show_text_completed(){
return (text_opacity() == 1); return (timer == null);
} }
</script> </script>
</head> </head>
@ -336,6 +326,7 @@ def build_lyrics_css(item, webkit_ver):
.lyricscell { .lyricscell {
display: table-cell; display: table-cell;
word-wrap: break-word; word-wrap: break-word;
-webkit-transition: opacity 0.4s ease;
%s %s
} }
.lyricsmain { .lyricsmain {

View File

@ -347,13 +347,14 @@ class MainDisplay(Display):
Generates a preview of the image displayed. Generates a preview of the image displayed.
""" """
log.debug(u'preview for %s', self.isLive) log.debug(u'preview for %s', self.isLive)
was_visible = self.isVisible()
self.application.process_events() self.application.process_events()
# We must have a service item to preview. # We must have a service item to preview.
if self.isLive and hasattr(self, u'serviceItem'): if self.isLive and hasattr(self, u'serviceItem'):
# Wait for the fade to finish before geting the preview. # Wait for the fade to finish before geting the preview.
# Important otherwise preview will have incorrect text if at all! # Important otherwise preview will have incorrect text if at all!
if self.serviceItem.themedata and self.serviceItem.themedata.display_slide_transition: 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() self.application.process_events()
# Wait for the webview to update before getting the preview. # Wait for the webview to update before getting the preview.
# Important otherwise first preview will miss the background ! # Important otherwise first preview will miss the background !
@ -363,7 +364,8 @@ class MainDisplay(Display):
if self.isLive: if self.isLive:
if self.hideMode: if self.hideMode:
self.hide_display(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 # Single screen active
if self.screens.display_count == 1: if self.screens.display_count == 1:
# Only make visible if setting enabled. # Only make visible if setting enabled.

View File

@ -7,7 +7,7 @@ from datetime import datetime, timedelta
from mock import MagicMock, patch from mock import MagicMock, patch
from openlp.core.lib import str_to_bool, translate, check_directory_exists, get_text_file_string, build_icon, \ 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): class TestLib(TestCase):
@ -299,6 +299,45 @@ class TestLib(TestCase):
MockedQtGui.QMessageBox.information.assert_called_with(u'parent', u'mocked translate', 'message') MockedQtGui.QMessageBox.information.assert_called_with(u'parent', u'mocked translate', 'message')
assert not result, u'The result should be False' 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): def validate_thumb_file_does_not_exist_test(self):
""" """
Test the validate_thumb() function when the thumbnail does not exist Test the validate_thumb() function when the thumbnail does not exist