Пример #1
0
 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")
Пример #2
0
    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")
Пример #3
0
    def handle_animation(self, widget, event, button_press=False):
        # Init.
        rect = widget.allocation

        start_x = rect.width + self.pointer_offset_x - self.pointer_radious
        start_y = rect.height + self.pointer_offset_y
        self.left_retangle = (0, 0, rect.width / 3, rect.height - self.pointer_offset_y)
        self.right_retangle = (0 + 2 * rect.width / 3, 0, rect.width / 3, rect.height - self.pointer_offset_y)

        if self.image_number > 1 and (
            start_y - 4 * self.pointer_radious < event.y < start_y + self.pointer_radious * 6
            and start_x - 2 * self.pointer_radious
            < event.x
            < start_x + 4 * self.pointer_padding + 4 * self.pointer_radious
        ):

            set_cursor(widget, gtk.gdk.HAND2)

            if self.hover_switch or button_press:
                self.motion_index = None
                for index in range(0, self.image_number):
                    if start_x + index * self.pointer_padding < event.x < start_x + (index + 1) * self.pointer_padding:
                        self.motion_index = index
                        if self.active_index != index:
                            self.start_animation(self.hover_animation_time, index)
                        break
        elif self.image_number > 1 and is_in_rect((event.x, event.y), self.left_retangle) and self.navigate_switch:
            if not self.in_left_nav:
                self.in_left_nav = True
                self.queue_draw()
            set_cursor(widget, gtk.gdk.SB_LEFT_ARROW)
            if button_press:
                self.to_left_animation()
        elif self.image_number > 1 and is_in_rect((event.x, event.y), self.right_retangle) and self.navigate_switch:
            if not self.in_right_nav:
                self.in_right_nav = True
                self.queue_draw()
            set_cursor(widget, gtk.gdk.SB_RIGHT_ARROW)
            if button_press:
                self.to_right_animation()
        else:
            if self.in_left_nav or self.in_right_nav:
                self.in_left_nav = False
                self.in_right_nav = False
                self.queue_draw()
            set_cursor(widget, None)

            if button_press:
                self.emit("button-press-index", self.active_index)
            else:
                self.emit("motion-notify-index", self.active_index)
Пример #4
0
 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()
Пример #5
0
    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"
Пример #6
0
 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"
Пример #7
0
 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()    
Пример #8
0
    def handle_animation(self, widget, event, button_press=False):
        # Init.
        rect = widget.allocation

        start_x = rect.width + self.pointer_offset_x - self.pointer_radious
        start_y = rect.height + self.pointer_offset_y
        self.left_retangle = (0, 0, rect.width/3, rect.height - self.pointer_offset_y)
        self.right_retangle = (0 + 2*rect.width/3, 0, rect.width/3, rect.height - self.pointer_offset_y)

        if self.image_number > 1 and (start_y - 4 * self.pointer_radious < event.y < start_y + self.pointer_radious * 6
            and start_x - 2 * self.pointer_radious < event.x < start_x + 4 * self.pointer_padding + 4 * self.pointer_radious):

            set_cursor(widget, gtk.gdk.HAND2)

            if self.hover_switch or button_press:
                self.motion_index = None
                for index in range(0, self.image_number):
                    if start_x + index * self.pointer_padding < event.x < start_x + (index + 1) * self.pointer_padding:
                        self.motion_index = index
                        if self.active_index != index:
                            self.start_animation(self.hover_animation_time, index)
                        break
        elif self.image_number > 1 and is_in_rect((event.x, event.y), self.left_retangle) and self.navigate_switch:
            if not self.in_left_nav:
                self.in_left_nav = True
                self.queue_draw()
            set_cursor(widget, gtk.gdk.SB_LEFT_ARROW)
            if button_press:
                self.to_left_animation()
        elif self.image_number > 1 and is_in_rect((event.x, event.y), self.right_retangle) and self.navigate_switch:
            if not self.in_right_nav:
                self.in_right_nav = True
                self.queue_draw()
            set_cursor(widget, gtk.gdk.SB_RIGHT_ARROW)
            if button_press:
                self.to_right_animation()
        else:
            if self.in_left_nav or self.in_right_nav:
                self.in_left_nav = False
                self.in_right_nav = False
                self.queue_draw()
            set_cursor(widget, None)

            if button_press:
                self.emit("button-press-index", self.active_index)
            else:
                self.emit("motion-notify-index", self.active_index)
Пример #9
0
 def leave_icon_view(self, widget, event):
     '''leave-notify-event signal handler.'''
     # Hide hover row when cursor out of viewport area.
     vadjust = get_match_parent(self, ["ScrolledWindow"]).get_vadjustment()
     hadjust = get_match_parent(self, ["ScrolledWindow"]).get_hadjustment()
     if not is_in_rect((event.x, event.y), 
                       (hadjust.get_value(), vadjust.get_value(), hadjust.get_page_size(), vadjust.get_page_size())):
         self.clear_focus_item()
Пример #10
0
 def get_close_button_at_event(self, event):
     hover_index = None
     for (index, item) in enumerate(self.tab_items):
         button_x = sum(self.tab_title_widths[0:index + 1]) - self.close_button_padding_x - self.close_button_size
         button_y = self.close_button_padding_y
         if is_in_rect((event.x, event.y), (button_x, button_y, self.close_button_size, self.close_button_size)):
             hover_index = index
             break
         
     return hover_index    
Пример #11
0
 def press_tab_title_box(self, widget, event):
     '''Press tab title box.'''
     for (index, item) in enumerate(self.tab_items):
         if is_in_rect((event.x, event.y), 
                       (sum(self.tab_title_widths[0:index]),
                        0,
                        self.tab_title_widths[index],
                        self.tab_height)):
             self.switch_content(index)
             break
Пример #12
0
    def leave_notify_slide_switcher(self, widget, event):
        rect = widget.allocation
        if is_in_rect((event.x, event.y), (0, 0, rect.width, rect.height)):
            self.handle_animation(widget, event)
        else:
            self.start_auto_slide()

        set_cursor(widget, None)

        self.emit("leave-notify-index", self.active_index)
Пример #13
0
    def leave_notify_slide_switcher(self, widget, event):
        rect = widget.allocation
        if is_in_rect((event.x, event.y), (0, 0, rect.width, rect.height)):
            self.handle_animation(widget, event)
        else:
            self.start_auto_slide()

        set_cursor(widget, None)

        self.emit("leave-notify-index", self.active_index)
Пример #14
0
    def is_in_button(self, x, y):
        '''
        Detection of wheter the mouse pointer is in the handler's button.
        '''
        handle = self.get_handle_window()
        (width, height) = handle.get_size()
        if self.get_orientation() == gtk.ORIENTATION_HORIZONTAL:
            rect = (0, (height - self.bheight) / 2, width, self.bheight)
        else:
            rect = ((width - self.bheight) / 2, 0, self.bheight, height)

        return is_in_rect((x, y), rect)
Пример #15
0
    def is_in_button(self, x, y):
        '''
        Detection of wheter the mouse pointer is in the handler's button.
        '''
        handle = self.get_handle_window()
        (width, height) = handle.get_size()
        if self.get_orientation() == gtk.ORIENTATION_HORIZONTAL:
            rect =  (0, (height - self.bheight) / 2, width, self.bheight)
        else:
            rect =  ((width - self.bheight) / 2, 0, self.bheight, height)

        return is_in_rect((x, y), rect)
Пример #16
0
    def is_in_button(self, x, y):
        handle = self.get_handle_window()
        (width, height) = handle.get_size()
        if self.get_orientation() == gtk.ORIENTATION_HORIZONTAL:
            rect =  (0, (height-self.bheight)/2, width, self.bheight)
        else:
            rect =  ((width-self.bheight)/2, 0, self.bheight, height)

        if is_in_rect((x, y), rect):
            return True
        else:
            return False
Пример #17
0
 def button_press_slider(self, widget, event):
     '''Button press slider.'''
     rect = widget.allocation
     (window_x, window_y) = widget.get_toplevel().window.get_origin()
     if (self.slide_index == self.slider_number - 1
         and is_in_rect((event.x_root, event.y_root), 
                        (window_x + rect.width - self.close_area_width,
                         window_y,
                         self.close_area_width,
                         self.close_area_height))):
         if self.finish_callback:
             self.finish_callback()
             
         self.destroy()    
     else:
         widget.connect("button-press-event", lambda w, e: move_window(w, e, self))            
Пример #18
0
    def press_tab_title_box(self, widget, event):
        '''
        Internal callback for `button-press-event` signal.
        '''
        close_tab_index = self.get_close_button_at_event(event)

        if close_tab_index != None:
            self.delete_items([self.tab_items[close_tab_index]])
        else:
            for (index, item) in enumerate(self.tab_items):
                if is_in_rect((event.x, event.y),
                              (sum(self.tab_title_widths[0:index]), 0,
                               self.tab_title_widths[index], self.tab_height)):
                    self.switch_content(index)
                    self.emit("switch-tab", index)
                    break
Пример #19
0
 def press_tab_title_box(self, widget, event):
     '''
     Internal callback for `button-press-event` signal.
     '''
     press_index = self.get_close_button_at_event(event)
     
     if press_index != None:
         self.delete_items([self.tab_items[press_index]])
     else:
         for (index, item) in enumerate(self.tab_items):
             if is_in_rect((event.x, event.y), 
                           (sum(self.tab_title_widths[0:index]),
                            0,
                            self.tab_title_widths[index],
                            self.tab_height)):
                 self.switch_content(index)
                 break
Пример #20
0
    def get_close_button_at_event(self, event):
        if self.can_close_tab:
            hover_index = None
            for (index, item) in enumerate(self.tab_items):
                button_x = sum(
                    self.tab_title_widths[0:index + 1]
                ) - self.close_button_padding_x - self.close_button_size
                button_y = self.close_button_padding_y
                if is_in_rect((event.x, event.y),
                              (button_x, button_y, self.close_button_size,
                               self.close_button_size)):
                    hover_index = index
                    break

            return hover_index
        # Return None if option can_close_tab is False.
        else:
            return None
Пример #21
0
    def do_button_press_event(self, e):
        '''
        when press the handler's button change the position.
        '''
        handle = self.get_handle_window()
        if e.window == handle:
            if self.is_in_button(e.x, e.y):
                self.init_button("press")

                self.do_press_actoin()
            else:
                (width, height) = handle.get_size()
                if is_in_rect((e.x, e.y), (0, 0, width, height)):
                    self.press_coordinate = (e.x, e.y)

                gtk.Paned.do_button_press_event(self, e)
        else:
            gtk.Paned.do_button_press_event(self, e)

        return True
Пример #22
0
 def do_button_press_event(self, e):
     '''
     when press the handler's button change the position.
     '''
     handle = self.get_handle_window()
     if e.window == handle:
         if self.is_in_button(e.x, e.y):
             self.init_button("press")
         
             self.do_press_actoin()
         else:
             (width, height) = handle.get_size()
             if is_in_rect((e.x, e.y), (0, 0, width, height)):
                 self.press_coordinate = (e.x, e.y)
         
             gtk.Paned.do_button_press_event(self, e)
     else:
         gtk.Paned.do_button_press_event(self, e)
         
     return True
Пример #23
0
class Droplist(gtk.Window):
    '''
    Droplist.

    @undocumented: create_item
    @undocumented: expose_item_align
    @undocumented: droplist_key_press
    @undocumented: droplist_key_release
    @undocumented: expose_droplist_frame
    @undocumented: init_droplist
    @undocumented: adjust_droplist_position
    '''

    __gsignals__ = {
        "item-selected": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (
            str,
            gobject.TYPE_PYOBJECT,
            int,
        )),
        "key-release": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (
            str,
            gobject.TYPE_PYOBJECT,
            int,
        )),
    }

    def __init__(self,
                 items,
                 x_align=ALIGN_START,
                 y_align=ALIGN_START,
                 font_size=DEFAULT_FONT_SIZE,
                 opacity=1.0,
                 padding_x=0,
                 padding_y=0,
                 item_padding_left=6,
                 item_padding_right=32,
                 item_padding_y=3,
                 max_width=None,
                 fixed_width=None,
                 max_height=None):
        '''
        Initialize Droplist class.

        @param items: A list of item, item format: (item_content, item_value).
        @param x_align: Horticultural alignment.
        @param y_align: Vertical alignment.
        @param font_size: Font size of droplist, default is DEFAULT_FONT_SIZE
        @param opacity: Opacity of droplist window, default is 1.0.
        @param padding_x: Padding x, default is 0.
        @param padding_y: Padding y, default is 0.
        @param item_padding_left: Padding at left of item, default is 6.
        @param item_padding_right: Padding at right of item, default is 32.
        @param item_padding_y: Padding of item vertically, default is 3.
        @param max_width: Maximum width of droplist, default is None.
        @param fixed_width: Fixed width of droplist, default is None.
        @param max_height: Maximum height of droplist, default is None.
        '''
        # Init.
        gtk.Window.__init__(self, gtk.WINDOW_POPUP)
        self.items = items
        self.set_can_focus(True)  # can focus to response key-press signal
        self.add_events(gtk.gdk.ALL_EVENTS_MASK)
        self.set_decorated(False)
        self.set_colormap(gtk.gdk.Screen().get_rgba_colormap())
        global root_droplists
        self.font_size = font_size
        self.x_align = x_align
        self.y_align = y_align
        self.subdroplist = None
        self.root_droplist = None
        self.offset_x = 0  # use for handle extreme situaiton, such as, droplist show at side of screen
        self.offset_y = 0
        self.padding_x = padding_x
        self.padding_y = padding_y
        self.item_padding_left = item_padding_left
        self.item_padding_right = item_padding_right
        self.item_padding_y = item_padding_y
        self.max_width = max_width
        self.max_height = max_height
        self.fixed_width = fixed_width
        self.item_select_index = 0

        # Init droplist window.
        self.set_opacity(opacity)
        self.set_skip_taskbar_hint(True)
        self.set_keep_above(True)
        self.connect_after("show", self.init_droplist)

        self.droplist_frame = gtk.Alignment()
        self.droplist_frame.set(0.5, 0.5, 1.0, 1.0)
        self.droplist_frame.set_padding(1, 1, 1, 1)

        # Add droplist item.
        self.item_box = gtk.VBox()
        self.item_align = gtk.Alignment()
        self.item_align.set_padding(padding_y, padding_y, padding_x, padding_x)
        self.item_align.add(self.item_box)
        self.item_scrolled_window = DroplistScrolledWindow(0, 0)
        self.item_scrolled_window.set_policy(gtk.POLICY_NEVER,
                                             gtk.POLICY_AUTOMATIC)
        self.add(self.droplist_frame)
        self.droplist_frame.add(self.item_scrolled_window)
        self.item_scrolled_window.add_child(self.item_align)
        self.droplist_items = []

        if items:
            for (index, item) in enumerate(items):
                droplist_item = self.create_item(index, item)
                self.droplist_items.append(droplist_item)
                self.item_box.pack_start(droplist_item.item_box, False, False)

        self.connect_after("show", lambda w: self.adjust_droplist_position())
        self.droplist_frame.connect("expose-event", self.expose_droplist_frame)
        self.item_align.connect("expose-event", self.expose_item_align)
        self.connect("key-press-event", self.droplist_key_press)
        self.connect("key-release-event", self.droplist_key_release)

        self.keymap = {
            "Home": self.select_first_item,
            "End": self.select_last_item,
            "Page_Up": self.scroll_page_up,
            "Page_Down": self.scroll_page_down,
            "Return": self.press_select_item,
            "Up": self.select_prev_item,
            "Down": self.select_next_item,
            "Escape": self.hide
        }

        self.select_first_item()
        self.grab_focus()

    def create_item(self, index, item):
        return DroplistItem(self, index, item, self.font_size, self.padding_x,
                            self.padding_y, self.item_padding_left,
                            self.item_padding_right, self.item_padding_y,
                            self.max_width, self.fixed_width)

    def get_droplist_width(self):
        '''
        Get droplist width.

        @return: Return width of droplist.
        '''
        if self.fixed_width != None:
            return self.padding_x * 2 + self.fixed_width
        else:
            item_content_width = max(
                map(
                    lambda item: get_content_size(item.item[0], self.font_size)
                    [0],
                    filter(lambda item: isinstance(item.item_box, gtk.Button),
                           self.droplist_items)))

            if self.max_width != None:
                return self.padding_x * 2 + min(
                    self.max_width, self.item_padding_left +
                    self.item_padding_right + int(item_content_width))
            else:
                return self.padding_x * 2 + self.item_padding_left + self.item_padding_right + int(
                    item_content_width)

    def expose_item_align(self, widget, event):
        '''
        Internal function to handle `expose-event` signal.

        @param widget: Droplist widget.
        @param event: Expose event.
        '''
        # Init.
        cr = widget.window.cairo_create()
        rect = widget.allocation
        x, y, w, h = rect.x, rect.y, rect.width, rect.height

        # Draw background.
        cr.set_source_rgba(*alpha_color_hex_to_cairo(
            ui_theme.get_alpha_color("droplist_mask").get_color_info()))
        cr.rectangle(x, y, w, h)
        cr.fill()

    def get_first_index(self):
        '''
        Get index of first item.

        @return: Return index of first item, or return None if haven't item in droplist.
        '''
        item_indexs = filter(
            lambda (index, item): isinstance(item.item_box, gtk.Button),
            enumerate(self.droplist_items))
        if len(item_indexs) > 0:
            return item_indexs[0][0]
        else:
            return None

    def get_last_index(self):
        '''
        Get index of last item.

        @return: Return index of last item, or return None if haven't item in droplist.
        '''
        item_indexs = filter(
            lambda (index, item): isinstance(item.item_box, gtk.Button),
            enumerate(self.droplist_items))
        if len(item_indexs) > 0:
            return item_indexs[-1][0]
        else:
            return None

    def get_prev_index(self):
        '''
        Get index of previous item.

        @return: Return index of previous item, or return None if haven't item in droplist.
        '''
        item_indexs = filter(
            lambda (index, item): isinstance(item.item_box, gtk.Button),
            enumerate(self.droplist_items))
        if len(item_indexs) > 0:
            index_list = map(lambda (index, item): index, item_indexs)
            if self.item_select_index in index_list:
                current_index = index_list.index(self.item_select_index)
                if current_index > 0:
                    return index_list[current_index - 1]
                else:
                    return self.item_select_index
            else:
                return None
        else:
            return None

    def get_next_index(self):
        '''
        Get index of next item.

        @return: Return index of next item, or return None if haven't item in droplist.
        '''
        item_indexs = filter(
            lambda (index, item): isinstance(item.item_box, gtk.Button),
            enumerate(self.droplist_items))
        if len(item_indexs) > 0:
            index_list = map(lambda (index, item): index, item_indexs)
            if self.item_select_index in index_list:
                current_index = index_list.index(self.item_select_index)
                if current_index < len(index_list) - 1:
                    return index_list[current_index + 1]
                else:
                    return self.item_select_index
            else:
                return None
        else:
            return None

    def get_select_item_rect(self, item_index=None):
        '''
        Get item rectangle with given index.

        @param item_index: If item_index is None, use select index.

        @return: Return (x, y, w, h) rectangle for match item.
        '''
        if item_index == None:
            item_index = self.item_select_index
        item_offset_y = sum(
            map(lambda item: item.item_box_height,
                self.droplist_items)[0:item_index])
        item_rect = self.droplist_items[item_index].item_box.get_allocation()
        return (0, item_offset_y, item_rect.width, item_rect.height)

    def active_item(self, item_index=None):
        '''
        Select item with given index.

        @param item_index: If item_index is None, use select index.
        '''
        global droplist_active_item

        if item_index == None:
            item_index = self.item_select_index

        if droplist_active_item:
            droplist_active_item.item_box.set_state(gtk.STATE_NORMAL)

        item = self.droplist_items[item_index]
        item.item_box.set_state(gtk.STATE_PRELIGHT)
        droplist_active_item = item

    def select_first_item(self):
        '''
        Select first item.
        '''
        if len(self.droplist_items) > 0:
            first_index = self.get_first_index()
            if first_index != None:
                self.item_select_index = first_index
                self.active_item()

                # Scroll to top.
                vadjust = self.item_scrolled_window.get_vadjustment()
                vadjust.set_value(vadjust.get_lower())

    def select_last_item(self):
        '''
        Select last item.
        '''
        if len(self.droplist_items) > 0:
            last_index = self.get_last_index()
            if last_index != None:
                self.item_select_index = last_index
                self.active_item()

                # Scroll to bottom.
                vadjust = self.item_scrolled_window.get_vadjustment()
                vadjust.set_value(vadjust.get_upper() -
                                  vadjust.get_page_size())

    def select_prev_item(self):
        '''
        Select previous item.
        '''
        if len(self.droplist_items) > 0:
            prev_index = self.get_prev_index()
            if prev_index != None:
                global droplist_active_item

                if droplist_active_item:
                    if self.item_select_index > 0:
                        self.item_select_index = prev_index
                        self.active_item()

                        # Make item in visible area.
                        (item_x, item_y, item_width,
                         item_height) = self.get_select_item_rect()
                        vadjust = self.item_scrolled_window.get_vadjustment()
                        if item_y < vadjust.get_value():
                            vadjust.set_value(item_y)
                else:
                    self.select_first_item()

    def select_next_item(self):
        '''
        Select next item.
        '''
        if len(self.droplist_items) > 0:
            next_index = self.get_next_index()
            if next_index != None:
                global droplist_active_item

                if droplist_active_item:
                    if self.item_select_index < len(self.droplist_items) - 1:
                        self.item_select_index = next_index
                        self.active_item()

                        # Make item in visible area.
                        (item_x, item_y, item_width,
                         item_height) = self.get_select_item_rect()
                        vadjust = self.item_scrolled_window.get_vadjustment()
                        if self.padding_y + item_y + item_height > vadjust.get_value(
                        ) + vadjust.get_page_size():
                            vadjust.set_value(self.padding_y * 2 + item_y +
                                              item_height -
                                              vadjust.get_page_size())
                else:
                    self.select_first_item()

    def scroll_page_to_select_item(self):
        '''
        Scroll page to select item.
        '''
        (item_x, item_y, item_width, item_height) = self.get_select_item_rect()
        vadjust = self.item_scrolled_window.get_vadjustment()
        vadjust.set_value(
            min(max(vadjust.get_lower(), item_y - self.padding_y * 2),
                vadjust.get_upper() - vadjust.get_page_size()))

    def scroll_page_up(self):
        '''
        Scroll page up.
        '''
        if len(self.droplist_items) > 0:
            # Scroll page up.
            vadjust = self.item_scrolled_window.get_vadjustment()
            vadjust.set_value(
                max(vadjust.get_lower(),
                    vadjust.get_value() - vadjust.get_page_size()))

            # Select nearest item.
            item_infos = map(
                lambda (index, item):
                (index, self.get_select_item_rect(index)),
                enumerate(self.droplist_items))
            for (index, (item_x, item_y, item_width,
                         item_height)) in item_infos:
                if item_y + self.padding_y > vadjust.get_value():
                    self.item_select_index = index
                    self.active_item()
                    break

    def scroll_page_down(self):
        '''
        Scroll page down.
        '''
        if len(self.droplist_items) > 0:
            # Scroll page up.
            vadjust = self.item_scrolled_window.get_vadjustment()
            vadjust.set_value(
                min(vadjust.get_upper() - vadjust.get_page_size(),
                    vadjust.get_value() + vadjust.get_page_size()))

            # Select nearest item.
            item_infos = map(
                lambda (index, item):
                (index, self.get_select_item_rect(index)),
                enumerate(self.droplist_items))
            item_infos.reverse()
            for (index, (item_x, item_y, item_width,
                         item_height)) in item_infos:
                if item_y + item_height + self.padding_y < vadjust.get_value(
                ) + vadjust.get_page_size():
                    self.item_select_index = index
                    self.active_item()
                    break

    def press_select_item(self):
        '''
        Press select item.
        '''
        if len(self.droplist_items) > 0:
            if 0 <= self.item_select_index < len(self.droplist_items):
                self.droplist_items[
                    self.item_select_index].wrap_droplist_clicked_action()

    def droplist_key_press(self, widget, event):
        '''
        Internal function for `key-press-event` signal.

        @param widget: Droplist widget.
        @param event: Key press event.
        '''
        key_name = get_keyevent_name(event)
        if self.keymap.has_key(key_name):
            self.keymap[key_name]()

        return True

    def droplist_key_release(self, widget, event):
        '''
        Internal function for `key-release-event` signal.

        @param widget: Droplist widget.
        @param event: Key release event.
        '''
        self.emit("key-release", self.items[self.item_select_index][0],
                  self.items[self.item_select_index][1],
                  self.item_select_index)

    def expose_droplist_frame(self, widget, event):
        '''
        Callback for `expose-event` siangl of droplist frame.

        @param widget: Droplist widget.
        @param event: Expose event.
        '''
        cr = widget.window.cairo_create()
        rect = widget.allocation

        with cairo_disable_antialias(cr):
            cr.set_line_width(1)
            cr.set_source_rgb(*color_hex_to_cairo(
                ui_theme.get_color("droplist_frame").get_color()))
            cr.rectangle(rect.x, rect.y, rect.width, rect.height)
            cr.fill()

    def get_droplist_item_at_coordinate(self, (x, y)):
        '''
        Get droplist item at coordinate, return None if haven't any droplist item at given coordinate.

        @param x: X coordiante.
        @param y: Y coordiante.

        @return: Return match item with given coordinate, return None if haven't any item match coordinate.
        '''
        match_droplist_item = None

        item_heights = map(lambda item: item.item_box_height,
                           self.droplist_items)
        item_offsets = map(lambda (index, height): sum(item_heights[0:index]),
                           enumerate(item_heights))

        vadjust = self.item_scrolled_window.get_vadjustment()
        (scrolled_window_x, scrolled_window_y) = get_widget_root_coordinate(
            self.item_scrolled_window, WIDGET_POS_TOP_LEFT)
        for (index, droplist_item) in enumerate(self.droplist_items):
            item_rect = droplist_item.item_box.get_allocation()
            if is_in_rect(
                (x, y),
                (scrolled_window_x, scrolled_window_y + item_offsets[index] -
                 (vadjust.get_value() - vadjust.get_lower()), item_rect.width,
                 item_rect.height)):
                match_droplist_item = droplist_item
                break

        return match_droplist_item
Пример #24
0
class Menu(Window):
    '''
    Menu.

    @undocumented: realize_menu
    @undocumented: hide_menu
    @undocumented: get_menu_item_at_coordinate
    @undocumented: get_menu_items
    @undocumented: init_menu
    @undocumented: get_submenus
    @undocumented: get_menu_icon_info
    @undocumented: adjust_menu_position
    @undocumented: show_submenu
    @undocumented: hide_submenu
    @undocumented: get_root_menu
    '''
    def __init__(self,
                 items,
                 is_root_menu=False,
                 select_scale=False,
                 x_align=ALIGN_START,
                 y_align=ALIGN_START,
                 font_size=DEFAULT_FONT_SIZE,
                 padding_x=3,
                 padding_y=3,
                 item_padding_x=6,
                 item_padding_y=3,
                 shadow_visible=True,
                 menu_min_width=130,
                 menu_item_select_color=None):
        '''
        Initialize Menu class.

        @param items: A list of item, item format: ((item_normal_dpixbuf, item_hover_dpixbuf, item_disable_dpixbuf), item_name, item_node).
        @param is_root_menu: Default is False for submenu, you should set it as True if you build root menu.
        @param select_scale: Default is False, it will use parant's width if it set True.
        @param x_align: Horizontal alignment value.
        @param y_align: Vertical alignment value.
        @param font_size: Menu font size, default is DEFAULT_FONT_SIZE
        @param padding_x: Horizontal padding value, default is 3 pixel.
        @param padding_y: Vertical padding value, default is 3 pixel.
        @param item_padding_x: Horizontal item padding value, default is 6 pixel.
        @param item_padding_y: Vertical item padding value, default is 3 pixel.
        @param shadow_visible: Whether show window shadow, default is True.
        @param menu_min_width: Minimum width of menu.
        '''
        global root_menus

        # Init.
        Window.__init__(self,
                        shadow_visible=shadow_visible,
                        window_type=gtk.WINDOW_POPUP,
                        shadow_radius=6)
        self.set_can_focus(True)  # can focus to response key-press signal
        self.draw_mask = self.draw_menu_mask
        self.is_root_menu = is_root_menu
        self.select_scale = select_scale
        self.x_align = x_align
        self.y_align = y_align
        self.submenu = None
        self.root_menu = None
        self.offset_x = 0  # use for handle extreme situaiton, such as, menu show at side of screen
        self.offset_y = 0
        self.padding_x = padding_x
        self.padding_y = padding_y
        self.item_padding_x = item_padding_x
        self.item_padding_y = item_padding_y
        self.menu_min_width = menu_min_width
        self.menu_item_select_color = menu_item_select_color

        # Init menu window.
        self.set_skip_pager_hint(True)
        self.set_skip_taskbar_hint(True)
        self.set_keep_above(True)

        # Add menu item.
        self.item_box = gtk.VBox()
        self.item_align = gtk.Alignment()
        self.item_align.set_padding(padding_y, padding_y, padding_x, padding_x)
        self.item_align.add(self.item_box)
        self.window_frame.add(self.item_align)
        self.menu_items = []
        self.font_size = font_size

        if items:
            self.add_menu_items(items)

        self.connect("show", self.init_menu)
        self.connect("hide", self.hide_menu)
        self.connect("realize", self.realize_menu)

    def set_mutual_icons(self, index, icons):
        # deepin-media-player useing.
        # other no use.
        for item in self.menu_items:
            item.set_item_icons(None)
        #
        self.menu_items[index].set_item_icons(icons)

    def add_menu_items(self, items):
        (icon_width, icon_height, have_submenu, submenu_width,
         submenu_height) = self.get_menu_icon_info(items)

        for item in items:
            menu_item = MenuItem(item, self.font_size, self.select_scale,
                                 self.show_submenu, self.hide_submenu,
                                 self.get_root_menu, self.get_menu_items,
                                 icon_width, icon_height, have_submenu,
                                 submenu_width, submenu_height, self.padding_x,
                                 self.padding_y, self.item_padding_x,
                                 self.item_padding_y, self.menu_min_width,
                                 self.menu_item_select_color)
            self.menu_items.append(menu_item)
            self.item_box.pack_start(menu_item.item_box, False, False)

    def clear_menus(self):
        self.menu_items = []
        self.item_align.remove(self.item_box)
        self.item_box = gtk.VBox()
        self.item_align.add(self.item_box)
        self.resize(1, 1)

    def hide_menu(self, widget):
        '''
        Internal callback for `hide` signal.
        '''
        # Avoid menu (popup window) show at (0, 0) when next show.
        self.move(-1000000, -1000000)

    def realize_menu(self, widget):
        '''
        Internal callback for `realize` signal.
        '''
        # Avoid menu (popup window) show at (0, 0) first.
        self.move(-1000000, -1000000)

        # Never draw background.
        self.window.set_back_pixmap(None, False)

    def draw_menu_mask(self, cr, x, y, w, h):
        '''
        Draw mask interface.

        @param cr: Cairo context.
        @param x: X coordinate of draw area.
        @param y: Y coordinate of draw area.
        @param w: Width of draw area.
        @param h: Height of draw area.
        '''
        # Draw background.
        cr.set_source_rgba(*alpha_color_hex_to_cairo(
            ui_theme.get_alpha_color("menu_mask").get_color_info()))
        cr.rectangle(x, y, w, h)
        cr.fill()

        # Draw left side.
        draw_hlinear(cr, x + 1, y + 1,
                     16 + self.padding_x + self.padding_x * 2, h - 2,
                     ui_theme.get_shadow_color("menu_side").get_color_info())

    def get_menu_item_at_coordinate(self, (x, y)):
        '''
        Internal function to get menu item at coordinate, return None if haven't any menu item at given coordinate.
        '''
        match_menu_item = None
        for menu_item in self.menu_items:
            item_rect = menu_item.item_box.get_allocation()
            (item_x,
             item_y) = get_widget_root_coordinate(menu_item.item_box,
                                                  WIDGET_POS_TOP_LEFT)
            if is_in_rect((x, y),
                          (item_x, item_y, item_rect.width, item_rect.height)):
                match_menu_item = menu_item
                break

        return match_menu_item