def handle_button_press(self, cr, rect, event_x, event_y): if self.is_expandable: if not self.in_animation: if self.has_expand: text_width, text_height = self.shrink_button_width, self.shrink_button_height else: text_width, text_height = self.expand_button_width, self.expand_button_height if is_in_rect((event_x, event_y), (rect.width - (rect.width - self.label_wrap_width) / 2 - text_width, rect.height - text_height, text_width, text_height)): if self.has_expand: start_position = self.expand_height animation_distance = self.init_height - self.expand_height else: start_position = self.init_height animation_distance = self.expand_height - self.init_height self.in_animation = True timeline = Timeline(self.animation_time, CURVE_SINE) timeline.connect('update', lambda source, status: self.update(source, status, start_position, animation_distance)) timeline.connect("completed", self.completed) timeline.run() else: print "no expand button"
def graph_package_deps(self, p, pngname): tl = Timeline() def epoch(t): return t.toordinal() #float(t.strftime("%s")) def authColor(p): return hashColor(self.author(p)) #depbar = "LightSkyBlue" #focalbar = "Yellow" reflbar = "PaleGoldenrod" vers_names = self.versions(p) # extend each version until the end of hte subsequent version for v,w in zip(vers_names[:-1], vers_names[1:]): # Lost author for author color tl.span(p, epoch(self.dc[p][v]), epoch(self.dc[p][w]), p + ":" + v, v, authColor(p), None) vlast = vers_names[-1] tl.span(p, epoch(self.dc[p][vlast]), epoch(self.end_of_time), p + ":" + vlast, vlast, authColor(p), None) for dep in self.dependencies(p): for (ref,st,en) in self.dep_version_spans(p, dep): tl.span(dep, epoch(st), epoch(en), dep + "::" + ref, ref, reflbar, "bottom") depvers = self.dep_versions(p, dep) try: vn2 = self.versions(dep) for vv,ww in zip(vn2[:-1], vn2[1:]): self.logwith( "deploop", vv,ww, self.dc[dep].keys()) tl.span(dep, epoch(self.dc[dep][vv]), epoch(self.dc[dep][ww]), dep + ":" + vv, vv, authColor(dep), "top") vvlast = vn2[-1] tl.span(dep, epoch(self.dc[dep][vvlast]), epoch(self.end_of_time), dep + ":" + vvlast, vvlast, authColor(dep), "top") except Exception, e: self.logwith("Exception processing dependency", dep, e) for vn in vers_names: if vn in depvers: dep_ver = self.extractVersionLimiter(depvers[vn]) self.logwith( dep_ver) destrec = tl.findByKey(dep + ":" + dep_ver) srcrec = tl.findByKey(p + ":" + vn) if len(destrec) > 0 and len(srcrec) > 0: tl.connect(destrec[0], srcrec[0]) self.logwith( "version", vn, "of", p, "did link to dependency", dep, "version", dep_ver) else: self.logwith( "version", vn, "of", p, "***can't*** find dependency", \ dep, "version", dep_ver, "lendestrec=", len(destrec), "lensrcrec=", len(srcrec)) else: self.logwith(vn,"is not in",list(depvers)) self.logwith( "version", vn, "of", p, "did not update dependency on", dep)
def start_animation(self, index, tab_start_x): if not self.in_animiation: self.in_animiation = True source_tab_x = tab_start_x + self.tab_index * self.tab_width target_tab_x = tab_start_x + index * self.tab_width timeline = Timeline(self.tab_animation_time, CURVE_SINE) timeline.connect('update', lambda source, status: self.update_animation(source, status, source_tab_x, (target_tab_x - source_tab_x))) timeline.connect("completed", lambda source: self.completed_animation(source, index)) timeline.run() self.emit("tab-switch-start", index)
def graph_package_downstreams(self, p, pngname): tl = Timeline() def epoch(t): return t.toordinal() #float(t.strftime("%s")) def authColor(p): return hashColor(self.author(p)) reflbar = "PaleGoldenrod" vers_names = self.versions(p) # Just show the first 20; the image gets too big otherwise for dep in list(self.reverse_dependencies(p))[:20]: for (ref,st,en) in self.dep_version_spans(dep, p): try: vname = str(ref).strip() if vname == "": vname = "*" except: self.logwith("Could not correct version name ", ref) vname = ref tl.span(dep, epoch(st), epoch(en), dep + "::" + ref, "-->" + vname, reflbar, "bottom", invisibleBar=True) depvers = self.dep_versions(dep, p) try: vn2 = self.versions(dep) for vv,ww in zip(vn2[:-1], vn2[1:]): self.logwith( "deploop", vv,ww, self.dc[dep].keys()) tl.span(dep, epoch(self.dc[dep][vv]), epoch(self.dc[dep][ww]), dep + ":" + vv, vv, authColor(dep), "top") vvlast = vn2[-1] tl.span(dep, epoch(self.dc[dep][vvlast]), epoch(self.end_of_time), dep + ":" + vvlast, vvlast, authColor(dep), "top") except Exception, e: self.logwith("Exception processing dependency", dep, e) for vn in vers_names: if vn in depvers: dep_ver = self.extractVersionLimiter(depvers[vn]) self.logwith( dep_ver) destrec = tl.findByKey(dep + ":" + dep_ver) srcrec = tl.findByKey(p + ":" + vn) if len(destrec) > 0 and len(srcrec) > 0: tl.connect(destrec[0], srcrec[0]) self.logwith( "version", vn, "of", p, "did link to dependency", dep, "version", dep_ver) else: self.logwith( "version", vn, "of", p, "***can't*** find dependency", \ dep, "version", dep_ver, "lendestrec=", len(destrec), "lensrcrec=", len(srcrec)) else: self.logwith(vn,"is not in",list(depvers)) self.logwith( "version", vn, "of", p, "did not update dependency on", dep)
def start_animation(self, animation_time, index=None): # Update ticker with active index if option index is None. if index == None: if self.active_index >= self.image_number - 1: index = 0 else: index = self.active_index + 1 if not self.in_animiation: self.in_animiation = True self.target_index = index timeline = Timeline(animation_time, CURVE_SINE) timeline.connect("update", self.update_animation) timeline.connect("completed", lambda source: self.completed_animation(source, index)) timeline.run() return True
def start_animation(self, animation_time, index=None): # Update ticker with active index if option index is None. if index == None: if self.active_index >= self.image_number - 1: index = 0 else: index = self.active_index + 1 if not self.in_animiation: self.in_animiation = True self.target_index = index timeline = Timeline(animation_time, CURVE_SINE) timeline.connect('update', self.update_animation) timeline.connect("completed", lambda source: self.completed_animation(source, index)) timeline.run() return True
def slide_to(self, widget): self.active_widget = widget def update(source, status): pos = end_position - start_position adjustment.set_value(start_position + int(round(status * pos))) adjustment = self.get_hadjustment() start_position = adjustment.get_value() end_position = widget.get_allocation().x if start_position != end_position: timeline = Timeline(500, CURVE_SINE) timeline.connect('update', update) timeline.run() if self.slide_callback: self.slide_callback(self.layout.get_children().index(widget), widget)
def set_value(self, value): if (not self.in_animation) and value != self.value: self.start_value = self.value self.range = value - self.value times = int(abs(self.range)) * 10 from timeline import Timeline, CURVE_SINE timeline = Timeline(times * 10, CURVE_SINE) timeline.connect("start", self.start_animation) timeline.connect("stop", self.stop_animation) timeline.connect("update", self.update_animation) timeline.run() return False
def set_value(self, value): if (not self.in_animation) and value != self.value: self.start_value = self.value self.range = value - self.value times = int(abs(self.range)) * 10 if times != 0: from timeline import Timeline, CURVE_SINE timeline = Timeline(times * 10, CURVE_SINE) timeline.connect("start", self.start_animation) timeline.connect("stop", self.stop_animation) timeline.connect("update", self.update_animation) timeline.run() else: self.value = value self.queue_draw() return False
class HSlider(gtk.Viewport): ''' HSlider class. @undocumented: slide_to_page @undocumented: set_to_page @undocumented: append_page ''' __gsignals__ = { "start_slide" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), "completed_slide" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), } def __init__(self, slide_time=200, ): ''' Initialize HSlider class. @param slide_time: The animation of slide time, default is 200ms. ''' gtk.Viewport.__init__(self) self.set_shadow_type(gtk.SHADOW_NONE) self.fixed = gtk.Fixed() self.add(self.fixed) self.slide_time = slide_time self.pre_widget = None self.active_widget = None self.connect("realize", self._update_size) self.connect("size_allocate", self._update_size) self.page_width = 0 self.page_height = 0 self.in_sliding = False def _update_size(self, w=None, _w=None): self.page_width = self.allocation.width self.page_height = self.allocation.height if self.active_widget: self.active_widget.set_size_request(self.page_width, self.page_height) if self.pre_widget: self.pre_widget.set_size_request(self.page_width, self.page_height) self.show_all() def _to_right(self, percent): self.offset = int(round(percent * self.page_width)) if self.pre_widget: self.fixed.move(self.pre_widget, - self.offset, 0) self.fixed.move(self.active_widget, self.page_width - self.offset, 0) def _to_left(self, percent): self.offset = int(round(percent * self.page_width)) if self.pre_widget: self.fixed.move(self.pre_widget, self.offset, 0) self.fixed.move(self.active_widget, self.offset - self.page_width, 0) def _no_effect(self): self.offset = self.page_width if self.pre_widget: self.fixed.remove(self.pre_widget) self.fixed.move(self.active_widget, 0, 0) def to_page(self, w, direction): ''' Slide to given page. @param w: gtk.Widget to slide. @param direction: The direction of slide animation, can use below value: - \"right\" slide from right to left - \"left\" slide from left to right - None no animation effect, slide directly ''' if self.in_sliding: return if w != self.active_widget: w.set_size_request(self.page_width, self.page_height) if w.parent != self.fixed: self.fixed.put(w, self.page_width, 0) self.active_widget = w self.timeline = Timeline(self.slide_time, CURVE_SINE) if direction == "right": self.timeline.connect('update', lambda source, status: self._to_right(status)) elif direction == "left": self.timeline.connect('update', lambda source, status: self._to_left(status)) else: self._no_effect() self.timeline.connect("start", lambda source: self._start()) self.timeline.connect("completed", lambda source: self._completed()) self.timeline.run() self.in_sliding = True self.show_all() def _start(self): self.emit("start_slide") def _completed(self): if self.pre_widget and self.pre_widget.parent == self.fixed: self.fixed.remove(self.pre_widget) self.pre_widget = self.active_widget #print "Pre: " + str(self.pre_widget) + " act: " + str(self.active_widget) + "children: " + str(self.get_children()) self.show_all() self.in_sliding = False self.emit("completed_slide") def to_page_now(self, w, d=None): ''' Slide to given page immediately. @param w: gtk.Widget to slide. ''' self.to_page(w, d) def slide_to_page(self, w, d): self.to_page(w, d) def set_to_page(self, w): self.to_page_now(w) def append_page(self, w): pass
class WizardBox(gtk.EventBox): ''' WizardBox class. @undocumented: init_size @undocumented: on_expose_event @undocumented: handle_animation @undocumented: on_motion_notify @undocumented: on_enter_notify @undocumented: on_leave_notify @undocumented: on_button_press @undocumented: auto_animation @undocumented: start_animation @undocumented: update_animation @undocumented: completed_animation ''' __gsignals__ = { 'close': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), } def __init__(self, slider_images=None, pointer_images=None, button_images=None, show_button=True, slide_delay=10000, ): ''' Initialize WizardBox class. @param slider_images: Slider images, default is None. @param pointer_images: Pointer images, default is None. @param pointer_images: Button images, default is None. @param show_button: Set as True to show button. @param slide_delay: The time of delay between slider image, default is 10000ms. ''' gtk.EventBox.__init__(self) self.set_visible_window(False) self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.ENTER_NOTIFY_MASK | gtk.gdk.LEAVE_NOTIFY_MASK ) self.connect("expose-event", self.on_expose_event) self.connect("motion-notify-event", self.on_motion_notify) self.connect("button-press-event", self.on_button_press) # Init images. self.slider_pixbufs = map(gtk.gdk.pixbuf_new_from_file, slider_images) self.slider_numuber = len(slider_images) self.dot_normal_pixbuf, self.dot_active_pixbuf = map(gtk.gdk.pixbuf_new_from_file, pointer_images) self.button_normal_pixbuf, self.button_press_pixbuf = map(gtk.gdk.pixbuf_new_from_file, button_images) self.close_dpixbuf = ui_theme.get_pixbuf("button/window_close_normal.png") self.show_button = show_button # Init sizes. self.init_size() self.pointer_coords = {} # Move animation. self.active_index = 0 self.target_index = None self.active_alpha = 1.0 self.target_index = 0.0 self.active_x = 0 self.target_x = None self.slider_y = 0 self.auto_animation_id = None self.auto_animation_timeout = slide_delay # millisecond. self.slider_timeout = 1000 # millisecond. self.in_animation = False self.motion_index = None self.auto_animation() def init_size(self): slider_pixbuf = self.slider_pixbufs[0] self.slider_width = slider_pixbuf.get_width() self.slider_height = slider_pixbuf.get_height() self.set_size_request(self.slider_width, self.slider_height) self.dot_width = self.dot_normal_pixbuf.get_width() self.dot_height = self.dot_normal_pixbuf.get_height() dot_spacing = 10 self.dot_width_offset = self.dot_width + dot_spacing dot_area_width = self.dot_width * self.slider_numuber + dot_spacing * (self.slider_numuber - 1) dot_offset_y = 40 self.dot_start_x = (self.slider_width - dot_area_width) / 2 self.dot_y = self.slider_height - dot_offset_y close_spacing = 0 close_x = self.slider_width - self.close_dpixbuf.get_pixbuf().get_width() - close_spacing close_y = close_spacing self.close_rect = gtk.gdk.Rectangle(close_x, close_y, self.close_dpixbuf.get_pixbuf().get_width(), self.close_dpixbuf.get_pixbuf().get_height()) button_bottom_size = 55 button_width = self.button_normal_pixbuf.get_width() button_height = self.button_normal_pixbuf.get_height() button_x = (self.slider_width - button_width) / 2 button_y = self.slider_height - button_height - button_bottom_size self.button_rect = gtk.gdk.Rectangle(button_x, button_y, button_width, button_height) def on_expose_event(self, widget, event): cr = widget.window.cairo_create() rect = widget.allocation cr.save() draw_pixbuf(cr, self.slider_pixbufs[self.active_index], rect.x + self.active_x, rect.x + self.slider_y, self.active_alpha) if self.target_index != None and self.target_x != None: draw_pixbuf(cr, self.slider_pixbufs[self.target_index], rect.x + self.target_x, rect.y + self.slider_y, self.target_alpha) cr.restore() # Draw select pointer. dot_start_x = rect.x + self.dot_start_x for index in range(self.slider_numuber): if self.target_index == None: if self.active_index == index: dot_pixbuf = self.dot_active_pixbuf else: dot_pixbuf = self.dot_normal_pixbuf else: if self.target_index == index: dot_pixbuf = self.dot_active_pixbuf else: dot_pixbuf = self.dot_normal_pixbuf pointer_rect = gtk.gdk.Rectangle( dot_start_x, rect.y + self.dot_y, self.dot_width, self.dot_height) self.pointer_coords[index] = pointer_rect draw_pixbuf(cr, dot_pixbuf, dot_start_x, rect.y + self.dot_y) dot_start_x += self.dot_width_offset # Draw close pixbuf. draw_pixbuf(cr, self.close_dpixbuf.get_pixbuf(), rect.x + self.close_rect.x, rect.y + self.close_rect.y) if self.show_button and self.target_index == self.slider_numuber - 1: if self.button_hover_flag: pixbuf = self.button_press_pixbuf else: pixbuf = self.button_normal_pixbuf draw_pixbuf(cr, pixbuf, rect.x + self.button_rect.x, rect.y + self.button_rect.y) return True def handle_animation(self, widget, event): self.motion_index = None for index, rect in self.pointer_coords.items(): if rect.x <= event.x <= rect.x + rect.width and rect.y <= event.y <= rect.y + rect.height: set_cursor(widget, gtk.gdk.HAND2) self.motion_index = index break else: self.motion_index = None set_cursor(widget, None) def on_motion_notify(self, widget, event): self.handle_animation(widget, event) if is_in_rect((event.x, event.y), self.button_rect): self.button_hover_flag = True else: self.button_hover_flag = False self.queue_draw() def on_enter_notify(self, widget, event): if self.auto_animation_id is not None: gobject.source_remove(self.auto_animation_id) self.auto_animation_id = None def on_leave_notify(self, widget, event): self.auto_animation() set_cursor(widget, None) def on_button_press(self, widget, event): if self.motion_index != None: self.start_animation(self.slider_timeout, self.motion_index) if is_in_rect((event.x, event.y), self.close_rect): self.emit("close") if is_in_rect((event.x, event.y), self.button_rect): self.emit("close") def auto_animation(self): self.auto_animation_id = gobject.timeout_add(self.auto_animation_timeout, lambda : self.start_animation(self.slider_timeout)) def start_animation(self, animation_time, target_index=None, direction="left"): if target_index is None: if self.active_index >= self.slider_numuber - 1: return False target_index = 0 else: target_index = self.active_index + 1 else: if target_index < self.active_index: direction = "right" if not self.in_animation: self.in_animation = True self.target_index = target_index self.timeline = Timeline(animation_time, CURVE_SINE) self.timeline.connect("update", lambda source, status: self.update_animation(source, status, direction)) self.timeline.connect("completed", lambda source: self.completed_animation(source, target_index)) self.timeline.run() return True def update_animation(self, source, status, direction): self.active_alpha = 1.0 - status self.target_alpha = status if direction == "right": self._to_right(status) else: self._to_left(status) self.queue_draw() def completed_animation(self, source, index): self.active_index = index self.active_alpha = 1.0 # self.target_index = None self.target_alpha = 0.0 self.in_animation = False self.active_x = 0 self.target_x = None self.queue_draw() def _to_right(self, status): self.active_x = self.slider_width * status self.target_x = 0 def _to_left(self, status): self.active_x = 0 - (self.slider_width * status) self.target_x = 0
class HSlider(gtk.Viewport): ''' HSlider class. @undocumented: slide_to_page @undocumented: set_to_page @undocumented: append_page ''' __gsignals__ = { "start_slide": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), "completed_slide": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), } def __init__( self, slide_time=200, ): ''' Initialize HSlider class. @param slide_time: The animation of slide time, default is 200ms. ''' gtk.Viewport.__init__(self) self.set_shadow_type(gtk.SHADOW_NONE) self.fixed = gtk.Fixed() self.add(self.fixed) self.slide_time = slide_time self.pre_widget = None self.active_widget = None self.connect("realize", self._update_size) self.connect("size_allocate", self._update_size) self.page_width = 0 self.page_height = 0 self.in_sliding = False def _update_size(self, w=None, _w=None): self.page_width = self.allocation.width self.page_height = self.allocation.height if self.active_widget: self.active_widget.set_size_request(self.page_width, self.page_height) if self.pre_widget: self.pre_widget.set_size_request(self.page_width, self.page_height) self.show_all() def _to_right(self, percent): self.offset = int(round(percent * self.page_width)) if self.pre_widget: self.fixed.move(self.pre_widget, -self.offset, 0) self.fixed.move(self.active_widget, self.page_width - self.offset, 0) def _to_left(self, percent): self.offset = int(round(percent * self.page_width)) if self.pre_widget: self.fixed.move(self.pre_widget, self.offset, 0) self.fixed.move(self.active_widget, self.offset - self.page_width, 0) def _no_effect(self): self.offset = self.page_width if self.pre_widget: self.fixed.remove(self.pre_widget) self.fixed.move(self.active_widget, 0, 0) def to_page(self, w, direction): ''' Slide to given page. @param w: gtk.Widget to slide. @param direction: The direction of slide animation, can use below value: - \"right\" slide from right to left - \"left\" slide from left to right - None no animation effect, slide directly ''' if self.in_sliding: return if w != self.active_widget: w.set_size_request(self.page_width, self.page_height) if w.parent != self.fixed: self.fixed.put(w, self.page_width, 0) self.active_widget = w self.timeline = Timeline(self.slide_time, CURVE_SINE) if direction == "right": self.timeline.connect( 'update', lambda source, status: self._to_right(status)) elif direction == "left": self.timeline.connect( 'update', lambda source, status: self._to_left(status)) else: self._no_effect() self.timeline.connect("start", lambda source: self._start()) self.timeline.connect("completed", lambda source: self._completed()) self.timeline.run() self.in_sliding = True self.show_all() def _start(self): self.emit("start_slide") def _completed(self): if self.pre_widget and self.pre_widget.parent == self.fixed: self.fixed.remove(self.pre_widget) self.pre_widget = self.active_widget #print "Pre: " + str(self.pre_widget) + " act: " + str(self.active_widget) + "children: " + str(self.get_children()) self.show_all() self.in_sliding = False self.emit("completed_slide") def to_page_now(self, w, d=None): ''' Slide to given page immediately. @param w: gtk.Widget to slide. ''' self.to_page(w, d) def slide_to_page(self, w, d): self.to_page(w, d) def set_to_page(self, w): self.to_page_now(w) def append_page(self, w): pass
class WizardBox(gtk.EventBox): ''' WizardBox class. @undocumented: init_size @undocumented: on_expose_event @undocumented: handle_animation @undocumented: on_motion_notify @undocumented: on_enter_notify @undocumented: on_leave_notify @undocumented: on_button_press @undocumented: auto_animation @undocumented: start_animation @undocumented: update_animation @undocumented: completed_animation ''' __gsignals__ = { 'close': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), } def __init__( self, slider_images=None, pointer_images=None, button_images=None, show_button=True, slide_delay=10000, ): ''' Initialize WizardBox class. @param slider_images: Slider images, default is None. @param pointer_images: Pointer images, default is None. @param pointer_images: Button images, default is None. @param show_button: Set as True to show button. @param slide_delay: The time of delay between slider image, default is 10000ms. ''' gtk.EventBox.__init__(self) self.set_visible_window(False) self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.ENTER_NOTIFY_MASK | gtk.gdk.LEAVE_NOTIFY_MASK) self.connect("expose-event", self.on_expose_event) self.connect("motion-notify-event", self.on_motion_notify) self.connect("button-press-event", self.on_button_press) # Init images. self.slider_pixbufs = map(gtk.gdk.pixbuf_new_from_file, slider_images) self.slider_numuber = len(slider_images) self.dot_normal_pixbuf, self.dot_active_pixbuf = map( gtk.gdk.pixbuf_new_from_file, pointer_images) self.button_normal_pixbuf, self.button_press_pixbuf = map( gtk.gdk.pixbuf_new_from_file, button_images) self.close_dpixbuf = ui_theme.get_pixbuf( "button/window_close_normal.png") self.show_button = show_button # Init sizes. self.init_size() self.pointer_coords = {} # Move animation. self.active_index = 0 self.target_index = None self.active_alpha = 1.0 self.target_index = 0.0 self.active_x = 0 self.target_x = None self.slider_y = 0 self.auto_animation_id = None self.auto_animation_timeout = slide_delay # millisecond. self.slider_timeout = 1000 # millisecond. self.in_animation = False self.motion_index = None self.auto_animation() def init_size(self): slider_pixbuf = self.slider_pixbufs[0] self.slider_width = slider_pixbuf.get_width() self.slider_height = slider_pixbuf.get_height() self.set_size_request(self.slider_width, self.slider_height) self.dot_width = self.dot_normal_pixbuf.get_width() self.dot_height = self.dot_normal_pixbuf.get_height() dot_spacing = 10 self.dot_width_offset = self.dot_width + dot_spacing dot_area_width = self.dot_width * self.slider_numuber + dot_spacing * ( self.slider_numuber - 1) dot_offset_y = 40 self.dot_start_x = (self.slider_width - dot_area_width) / 2 self.dot_y = self.slider_height - dot_offset_y close_spacing = 0 close_x = self.slider_width - self.close_dpixbuf.get_pixbuf( ).get_width() - close_spacing close_y = close_spacing self.close_rect = gtk.gdk.Rectangle( close_x, close_y, self.close_dpixbuf.get_pixbuf().get_width(), self.close_dpixbuf.get_pixbuf().get_height()) button_bottom_size = 55 button_width = self.button_normal_pixbuf.get_width() button_height = self.button_normal_pixbuf.get_height() button_x = (self.slider_width - button_width) / 2 button_y = self.slider_height - button_height - button_bottom_size self.button_rect = gtk.gdk.Rectangle(button_x, button_y, button_width, button_height) def on_expose_event(self, widget, event): cr = widget.window.cairo_create() rect = widget.allocation cr.save() draw_pixbuf(cr, self.slider_pixbufs[self.active_index], rect.x + self.active_x, rect.x + self.slider_y, self.active_alpha) if self.target_index != None and self.target_x != None: draw_pixbuf(cr, self.slider_pixbufs[self.target_index], rect.x + self.target_x, rect.y + self.slider_y, self.target_alpha) cr.restore() # Draw select pointer. dot_start_x = rect.x + self.dot_start_x for index in range(self.slider_numuber): if self.target_index == None: if self.active_index == index: dot_pixbuf = self.dot_active_pixbuf else: dot_pixbuf = self.dot_normal_pixbuf else: if self.target_index == index: dot_pixbuf = self.dot_active_pixbuf else: dot_pixbuf = self.dot_normal_pixbuf pointer_rect = gtk.gdk.Rectangle(dot_start_x, rect.y + self.dot_y, self.dot_width, self.dot_height) self.pointer_coords[index] = pointer_rect draw_pixbuf(cr, dot_pixbuf, dot_start_x, rect.y + self.dot_y) dot_start_x += self.dot_width_offset # Draw close pixbuf. draw_pixbuf(cr, self.close_dpixbuf.get_pixbuf(), rect.x + self.close_rect.x, rect.y + self.close_rect.y) if self.show_button and self.target_index == self.slider_numuber - 1: if self.button_hover_flag: pixbuf = self.button_press_pixbuf else: pixbuf = self.button_normal_pixbuf draw_pixbuf(cr, pixbuf, rect.x + self.button_rect.x, rect.y + self.button_rect.y) return True def handle_animation(self, widget, event): self.motion_index = None for index, rect in self.pointer_coords.items(): if rect.x <= event.x <= rect.x + rect.width and rect.y <= event.y <= rect.y + rect.height: set_cursor(widget, gtk.gdk.HAND2) self.motion_index = index break else: self.motion_index = None set_cursor(widget, None) def on_motion_notify(self, widget, event): self.handle_animation(widget, event) if is_in_rect((event.x, event.y), self.button_rect): self.button_hover_flag = True else: self.button_hover_flag = False self.queue_draw() def on_enter_notify(self, widget, event): if self.auto_animation_id is not None: gobject.source_remove(self.auto_animation_id) self.auto_animation_id = None def on_leave_notify(self, widget, event): self.auto_animation() set_cursor(widget, None) def on_button_press(self, widget, event): if self.motion_index != None: self.start_animation(self.slider_timeout, self.motion_index) if is_in_rect((event.x, event.y), self.close_rect): self.emit("close") if is_in_rect((event.x, event.y), self.button_rect): self.emit("close") def auto_animation(self): self.auto_animation_id = gobject.timeout_add( self.auto_animation_timeout, lambda: self.start_animation(self.slider_timeout)) def start_animation(self, animation_time, target_index=None, direction="left"): if target_index is None: if self.active_index >= self.slider_numuber - 1: return False target_index = 0 else: target_index = self.active_index + 1 else: if target_index < self.active_index: direction = "right" if not self.in_animation: self.in_animation = True self.target_index = target_index self.timeline = Timeline(animation_time, CURVE_SINE) self.timeline.connect( "update", lambda source, status: self.update_animation( source, status, direction)) self.timeline.connect( "completed", lambda source: self.completed_animation(source, target_index)) self.timeline.run() return True def update_animation(self, source, status, direction): self.active_alpha = 1.0 - status self.target_alpha = status if direction == "right": self._to_right(status) else: self._to_left(status) self.queue_draw() def completed_animation(self, source, index): self.active_index = index self.active_alpha = 1.0 # self.target_index = None self.target_alpha = 0.0 self.in_animation = False self.active_x = 0 self.target_x = None self.queue_draw() def _to_right(self, status): self.active_x = self.slider_width * status self.target_x = 0 def _to_left(self, status): self.active_x = 0 - (self.slider_width * status) self.target_x = 0