Package elisa :: Package plugins :: Package bad :: Package raval_frontend :: Package raval_widgets :: Module long_loading_image
[hide private]
[frames] | no frames]

Source Code for Module elisa.plugins.bad.raval_frontend.raval_widgets.long_loading_image

  1  # -*- mode: python; coding: utf-8 -*- 
  2  # 
  3  # Pigment Python tools 
  4  # 
  5  # Copyright © 2006-2008 Fluendo Embedded S.L. 
  6  # 
  7  # This library is free software; you can redistribute it and/or 
  8  # modify it under the terms of the GNU Lesser General Public 
  9  # License as published by the Free Software Foundation; either 
 10  # version 2 of the License, or (at your option) any later version. 
 11  # 
 12  # This library is distributed in the hope that it will be useful, 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 15  # Lesser General Public License for more details. 
 16  # 
 17  # You should have received a copy of the GNU Lesser General Public 
 18  # License along with this library; if not, write to the 
 19  # Free Software Foundation, Inc., 59 Temple Place - Suite 330, 
 20  # Boston, MA 02111-1307, USA. 
 21   
 22  import math 
 23   
 24  import pgm 
 25  from pgm.graph.group import Group 
 26  from pgm.graph.image import Image 
 27  from pgm.timing import implicit 
 28   
 29  from twisted.internet import reactor 
 30   
31 -class LongLoadingImage(Group):
32 """ 33 Widget providing facilities for displaying a temporary quickly loaded 34 image while a bigger one is being loaded. 35 36 Display L{quick_image} and then L{image} when it is finished loading. 37 38 Also supports a rotating image on top to notify loadings. 39 40 @ivar image: image that can take time to load 41 @type image: L{pgm.graph.image.Image} 42 @ivar quick_image: image quick to load 43 @type quick_image: L{pgm.graph.image.Image} 44 @ivar loading: DOCME 45 @type loading: bool 46 @ivar loading_image_path: DOCME 47 @type loading_image_path: str 48 49 @cvar time_before_quick: DOCME 50 @type time_before_quick: float 51 @cvar time_before_loading: DOCME 52 @type time_before_loading: float 53 """ 54 55 time_before_quick = 0.250 56 time_before_loading = 0.250 57
58 - def __init__(self):
59 Group.__init__(self) 60 61 # image creation 62 self._image = Image() 63 self.add(self._image) 64 self._image.bg_color = (0, 0, 0, 0) 65 self._image.opacity = 0 66 self._image.layout = pgm.IMAGE_SCALED 67 self._image.visible = False 68 self._image.connect("pixbuf-loaded", self._image_loaded) 69 70 settings = {'duration': 300, 71 'transformation': implicit.SMOOTH, 72 'end_callback' : lambda c: self._hide_quick_image() 73 } 74 75 attributes = ('opacity',) 76 self._animated_image = implicit.AnimatedObject(self._image, attributes) 77 self._animated_image.setup_next_animations(**settings) 78 79 # quick image initialisation 80 self._quick_image = None 81 self._quick_image_call = None 82 83 # loading image initialisation 84 self._loading = False 85 self._loading_image = None 86 self._loading_image_path = None 87 self._loading_call = None 88 self._rotation_matrix = None 89 self._rotation_call = None
90
91 - def image__get(self):
92 return self._image
93
94 - def _image_loaded(self, image):
95 # cancel the delayed loading of quick image 96 if self._quick_image_call != None and self._quick_image_call.active(): 97 self._quick_image_call.cancel() 98 99 # fade in the image 100 self._animated_image.stop_animations() 101 self._image.opacity = 0 102 self._image.visible = True 103 self._animated_image.opacity = 255
104
105 - def _create_quick_image(self):
106 # Quick image is created on demand 107 if self._quick_image == None: 108 self._quick_image = Image() 109 self._quick_image.size = self.size 110 self.add(self._quick_image) 111 self._quick_image.z -= 0.001 112 self._quick_image.bg_color = (0, 0, 0, 0) 113 self._quick_image.layout = pgm.IMAGE_SCALED 114 self._quick_image.visible = False 115 self._quick_image.connect("pixbuf-loaded", self._quick_image_loaded)
116
117 - def quick_image__get(self):
118 # FIXME : fake the emission of the signal 'pixbuf-loaded' because there 119 # is no notification when a set_from_image is done and, in our use case, 120 # quick_image__get is used to set a clone. Pigment needs a signal to 121 # notify changes to the master image. 122 self._create_quick_image() 123 self._quick_image_loaded(self._quick_image) 124 return self._quick_image
125
126 - def _quick_image_loaded(self, image):
127 # cancel previous delayed loading of quick image 128 if self._quick_image_call != None and self._quick_image_call.active(): 129 self._quick_image_call.cancel() 130 131 self._quick_image_call = reactor.callLater(self.time_before_quick, 132 self._show_quick_image)
133
134 - def _show_quick_image(self):
135 if self._quick_image != None: 136 self._quick_image.opacity = 255 137 self._quick_image.visible = True
138
139 - def _hide_quick_image(self):
140 if self._quick_image != None: 141 self._quick_image.visible = False 142 self.remove(self._quick_image) 143 self._quick_image = None
144
145 - def loading_image_path__set(self, path):
146 self._loading_image_path = path 147 if self._loading_image != None: 148 self._loading_image.set_from_file(path)
149
150 - def _create_loading_image(self):
151 # Loading image is created on demand 152 if self._loading_image == None: 153 self._loading_image = Image() 154 self._loading_image.size = self.size 155 self.add(self._loading_image) 156 self._loading_image.bg_color = (0, 0, 0, 0) 157 self._loading_image.layout = pgm.IMAGE_SCALED 158 self._loading_image.visible = False 159 160 self._rotation_matrix = pgm.mat4x4_new_identity() 161 self._rotation_matrix.translate(0.5, 0.5, 0.0) 162 self._rotation_matrix.rotate_z(math.pi / 30.0) 163 self._rotation_matrix.translate(-0.5, -0.5, 0.0) 164 if self._loading_image_path: 165 self._loading_image.set_from_file(self._loading_image_path)
166
167 - def loading__set(self, loading):
168 self._loading = loading 169 170 # cancel the delayed starting of loading animation 171 if self._loading_call != None and self._loading_call.active(): 172 self._loading_call.cancel() 173 174 if loading == True: 175 self._loading_call = reactor.callLater(self.time_before_loading, 176 self._start_loading_animation) 177 else: 178 # cancel the rotating animation if any 179 if self._loading_call != None and self._loading_call.active(): 180 self._rotation_call.cancel() 181 182 if self._loading_image != None: 183 self.remove(self._loading_image) 184 self._loading_image = None
185
186 - def loading__get(self):
187 return self._loading
188
189 - def _start_loading_animation(self):
190 if self._loading_image_path != None: 191 if self._loading_image == None: 192 self._create_loading_image() 193 self._loading_image.visible = self.loading 194 195 # start rotating animation if needed 196 if self._loading_call == None or not self._loading_call.active(): 197 self._rotation_call = reactor.callLater(0.017, 198 self._rotate_loading)
199
200 - def _rotate_loading(self):
201 if self._loading_image: 202 self._loading_image.mapping_matrix *= self._rotation_matrix 203 if self._loading: 204 self._rotation_call = reactor.callLater(0.017, 205 self._rotate_loading)
206