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

Source Code for Module elisa.plugins.bad.raval_frontend.coverflow_list_view

  1  # -*- coding: utf-8 -*- 
  2  # Elisa - Home multimedia server 
  3  # Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com). 
  4  # All rights reserved. 
  5  # 
  6  # This file is available under one of two license agreements. 
  7  # 
  8  # This file is licensed under the GPL version 3. 
  9  # See "LICENSE.GPL" in the root of this distribution including a special 
 10  # exception to use Elisa with Fluendo's plugins. 
 11  # 
 12  # The GPL part of Elisa is also available under a commercial licensing 
 13  # agreement from Fluendo. 
 14  # See "LICENSE.Elisa" in the root directory of this distribution package 
 15  # for details on that license. 
 16   
 17  from elisa.core import common 
 18  import constants 
 19   
 20  import pgm 
 21  from pgm.graph.group import Group 
 22  from pgm.graph.image import Image 
 23  from pgm.graph.text import Text 
 24  from pgm.utils import maths 
 25  from pgm.widgets.list_ng import List 
 26  from pgm.widgets import const 
 27  from pgm.utils.image import cairo_gradient 
 28   
 29   
30 -class ListItem(Group):
31
32 - def __init__(self):
33 Group.__init__(self) 34 35 # preview drawable 36 self.image = Image() 37 self.add(self.image, True) 38 self.image.bg_a = 0 39 self.image.layout = pgm.IMAGE_ZOOMED 40 # self.image.layout = pgm.IMAGE_SCALED 41 self.image.alignment = pgm.IMAGE_BOTTOM 42 self.image.border_inner_color = (255, 255, 255, 255) 43 self.image.border_outer_color = (255, 255, 255, 255) 44 self.image.visible = True 45 46 # reflection drawable 47 self.reflection = Image() 48 self.add(self.reflection) 49 flip_matrix = pgm.mat4x4_new_predefined(pgm.MAT4X4_FLIP_VERTICAL) 50 self.reflection.mapping_matrix = flip_matrix 51 self.reflection.bg_a = 0 52 self.reflection.layout = pgm.IMAGE_ZOOMED 53 # self.reflection.layout = pgm.IMAGE_SCALED 54 self.reflection.opacity = 100 55 self.reflection.y += self.image.height#*0.98 56 self.reflection.alignment = pgm.IMAGE_TOP 57 self.reflection.visible = True
58 59 60 61 plugin_registry = common.application.plugin_registry 62 BaseListView = plugin_registry.get_component_class('raval:list_view') 63
64 -class CoverflowListView(BaseListView, List):
65
66 - def create_widgets(self):
67 super(CoverflowListView, self).create_widgets() 68 69 canvas = self.frontend.context.viewport_handle.get_canvas() 70 theme = self.frontend.theme 71 72 self.orientation = const.HORIZONTAL 73 self.width = canvas.width * 0.9 74 self.height = canvas.height * 0.8 75 self.x = (canvas.width - self.width)/2.0 76 self.y = (canvas.height - self.height)/2.0 77 self.visible_range_size = 9 78 79 self.sub_description = Text() 80 self.add(self.sub_description) 81 self.sub_description.font_family = "Nimbus Sans L Bold" 82 self.sub_description.fg_color = (150, 150, 150, 255) 83 self.sub_description.alignment = pgm.TEXT_ALIGN_CENTER 84 self.sub_description.ellipsize = pgm.TEXT_ELLIPSIZE_MIDDLE 85 self.sub_description.font_height = 0.2 86 self.sub_description.bg_a = 0 87 self.sub_description.width = self.width * 0.95 88 self.sub_description.height = self.height * 0.1 89 x = (self.width - self.sub_description.width) / 2.0 90 y = self.height - self.sub_description.height / 2.0 91 self.sub_description.position = (x, y, 0.0) 92 self.sub_description.visible = True 93 94 self.description = Text() 95 self.add(self.description) 96 self.description.font_family = "Nimbus Sans L Bold" 97 self.description.alignment = pgm.TEXT_ALIGN_CENTER 98 self.description.ellipsize = pgm.TEXT_ELLIPSIZE_MIDDLE 99 self.description.font_height = 0.21 100 self.description.bg_a = 0 101 self.description.width = self.width * 0.95 102 self.description.height = self.height * 0.1 103 x = (self.width - self.description.width) / 2.0 104 y = self.height - self.sub_description.height - self.description.height / 2.0 105 self.description.position = (x, y, 0.0) 106 self.description.visible = True 107 108 #back button at bottom left corner of the list 109 self._back_img = Image() 110 self._back_img.connect("clicked", self._back_button_clicked) 111 self._back_img.layout = pgm.IMAGE_SCALED 112 self.load_from_theme("list_mode_back_button", self._back_img) 113 self._back_img.bg_color = (0, 0, 0, 0) 114 self._back_img.visible = True 115 height = canvas.height * constants.back_button_height / 100. 116 width = canvas.width / 8.0 117 y = canvas.height - self.y - height 118 x = -self.x 119 self._back_img.alignment = pgm.IMAGE_BOTTOM_LEFT 120 self._back_img.position = (x, y, 0) 121 self._back_img.size = (width, height) 122 self.add(self._back_img)
123
124 - def _back_button_clicked(self, drawable, x, y, z, button, time):
125 canvas = self.frontend.context.viewport_handle.get_canvas() 126 canvas.remove(self._back_img) 127 self.controller.parent.exit_node() 128 return True
129
130 - def create_item(self, model):
131 widget = ListItem() 132 return widget
133
134 - def load_item(self, index):
135 gradient = 0.4 136 model = self.controller.model[index] 137 widget = self[index] 138 139 self.load_from_theme(model.theme_icon, widget.image) 140 icon = self.frontend.theme.get_media(model.theme_icon) 141 cairo_gradient(icon, widget.reflection, gradient) 142 143 uri = model.thumbnail_source 144 if uri != None: 145 self._thumbnail_source_to_image(uri, widget) 146 else: 147 self._create_image_stack(model, widget.image, 148 reflection=widget.reflection, 149 gradient = gradient)
150
151 - def unload_item(self, widget):
152 widget.image.clear() 153 widget.reflection.clear() 154 widget.image.border_width = 0.0
155
156 - def insert(self, index, widget):
157 widget.connect('clicked', self._child_clicked) 158 super(CoverflowListView, self).insert(index, widget)
159
160 - def _child_clicked(self, drawable, x, y, z, button, time):
161 index = self.widgets.index(drawable) 162 self.emit('child-clicked', index) 163 return True
164
165 - def do_clicked(self, x, y, z, button, time):
166 # always let the children handle the clicks 167 return False
168
169 - def do_child_clicked(self, index):
170 old_selected = self.selected_item 171 super(CoverflowListView, self).do_child_clicked(index) 172 173 if old_selected == self.selected_item: 174 return self.controller.activate_item(self.frontend)
175
176 - def do_selected_item_changed(self, index):
177 self._controller.current_index = index
178
179 - def element_attribute_set(self, position, key, old_value, new_value):
180 super(CoverflowListView, self).element_attribute_set(position, key, 181 old_value, new_value) 182 if key == "text": 183 text = self.frontend.translate_text(new_value) 184 self[position].description = text 185 elif key == "thumbnail_source": 186 if self.is_widget_visible(position): 187 self._thumbnail_source_to_image(new_value, self[position])
188
189 - def _piecewise_interpolation(self, x, y, factor):
190 t = self._visible_range_size-1.0 191 x = map(lambda a: t*a, x) 192 193 # clamp after lower and upper limits 194 if factor < x[0]: 195 return y[0] 196 elif factor > x[-1]: 197 return y[-1] 198 else: 199 # general case: looking for the segment where factor belongs 200 i = 0 201 while factor > x[i+1]: 202 i += 1 203 204 # factor must be between 0.0 and 1.0 205 new_factor = (factor - x[i]) / (x[i+1] - x[i]) 206 return maths.lerp(y[i], y[i+1], new_factor)
207
208 - def compute_x(self, index):
209 w = self._width 210 x = [0.0, 0.4, 0.5, 0.6, 1.0] 211 y = [0.0, w*0.1, w*0.5, w*0.9, w] 212 y = [e-self._widget_width/2.0 for e in y] 213 214 return self._piecewise_interpolation(x, y, index)
215
216 - def compute_y(self, index):
217 # center the items 218 # assuming that each item has a reflection of the same height as 219 # itself 220 return self._height/4.0
221
222 - def compute_z(self, index):
223 min_z = -200.0 224 max_z = 200.0 225 226 x = [0.0, 0.4, 0.5, 0.6, 1.0] 227 y = [min_z, min_z/2.0, max_z, min_z/2.0, min_z] 228 229 return self._piecewise_interpolation(x, y, index)
230
231 - def compute_opacity(self, index):
232 x = [0.0, 0.4, 0.47, 0.53, 0.6, 1.0] 233 y = [50, 200, 255, 255, 200, 50] 234 235 return self._piecewise_interpolation(x, y, index)
236
237 - def layout_widget(self, widget, position):
238 zoom = 0.9 239 width = self._widget_height/2.0*zoom 240 height = self._widget_height*zoom 241 242 # update widget properties 243 x = self.compute_x(position)-(width-self._widget_width)/2.0 244 y = self.compute_y(position)-(height-self._widget_height)/2.0 245 z = self.compute_z(position) 246 widget.position = (x, y, z) 247 248 # FIXME: hackish 249 o = self.compute_opacity(position) 250 c = (o, o, o, 255) 251 widget.image.fg_color = c 252 widget.image.border_inner_a = o 253 widget.image.border_outer_a = o 254 widget.reflection.fg_color = c 255 widget.opacity = 255 256 257 widget.size = (width, height)
258
259 - def selected_item__get(self):
260 return self._selected_item
261
262 - def selected_item__set(self, index):
263 super(CoverflowListView, self).selected_item__set(index) 264 self._stop_deceleration() 265 index = maths.clamp(index, 0, len(self.widgets)-1) 266 index = int(round(index)) 267 268 half_size = (self.visible_range_size-1.0)/2.0 269 prev_selected = self._selected_item 270 self._selected_item = index 271 self._animated.visible_range_start = index-half_size 272 273 if prev_selected != index: 274 self.emit('selected-item-changed', index)
275
276 - def _thumbnail_source_to_image(self, uri, image):
277 try: 278 dfr = common.application.media_manager.get_media_type(uri) 279 except MediaProviderNotFound, e: 280 self.info("Could not make a thumbnail for %s: no MediaProvider" 281 " found for this kind of URI (scheme: %s)" % (uri, 282 uri.scheme)) 283 # If there is no provider for this uri existing, we can't go on 284 return 285 286 def error(error): 287 self.warning(error) 288 if self.frontend: 289 self.load_from_theme("unknown_icon", image.image) 290 image_path = self.frontend.theme.get_media('unknown_icon') 291 cairo_gradient(image_path, image.reflection, 0.4) 292 return image_path
293 294 def got_media_type(media_type): 295 file_type = media_type["file_type"] 296 dfr2 = common.application.thumbnailer.get_thumbnail(uri, 297 256, 298 file_type) 299 def display(result): 300 image_path = result[0] 301 302 def load_reflection(drawable): 303 image.image.border_width = self._widget_width*0.04 304 cairo_gradient(result[0], image.reflection, 0.4)
305 306 image.image.connect("pixbuf-loaded", load_reflection) 307 image.image.set_from_file(image_path) 308 return image_path 309 310 dfr2.addCallback(display).addErrback(error) 311 return dfr2 312 313 dfr.addCallback(got_media_type).addErrback(error) 314 return dfr 315
316 - def update_details(self):
317 self.debug("updating the title") 318 if self.selected_item >= 0 and len(self.controller.model): 319 model = self.controller.model[self.selected_item] 320 text = self.frontend.translate_text(model.text) 321 sub_text = self.frontend.translate_text(model.sub_text) 322 self.description.label = text 323 self.sub_description.label = sub_text
324