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 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)
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 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 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)
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()
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
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
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)
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)
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
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))
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
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
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
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
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
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