Beispiel #1
0
 def create_simple_button(self, name, callback=None):
     button = DisableButton(
         (
             ui_theme.get_pixbuf("spin/spin_arrow_%s_normal.png" % name),
             ui_theme.get_pixbuf("spin/spin_arrow_%s_hover.png" % name),
             ui_theme.get_pixbuf("spin/spin_arrow_%s_press.png" % name),
             ui_theme.get_pixbuf("spin/spin_arrow_%s_disable.png" % name),
         )
     )
     if callback:
         button.connect("button-press-event", callback)
         button.connect("button-release-event", self.handle_key_release)
     return button
Beispiel #2
0
 def __init__(self, items, droplist_height=None, select_index=0, max_width=None):
     '''Init combo box.'''
     # Init.
     gtk.VBox.__init__(self)
     self.set_can_focus(True)
     self.items = items
     self.droplist_height = droplist_height
     self.select_index = select_index
     self.focus_flag = False
     
     self.droplist = Droplist(self.items, max_width=max_width)
     if self.droplist_height:
         self.droplist.set_size_request(-1, self.droplist_height)
     self.width = self.droplist.get_droplist_width() 
     self.height = 22
     self.label_padding_left = 6
     self.box = gtk.HBox()
     self.dropbutton_width = ui_theme.get_pixbuf("combo/dropbutton_normal.png").get_pixbuf().get_width()
     self.label = Label(self.items[select_index][0], 
                        label_width=self.width - self.dropbutton_width - 1 - self.label_padding_left,
                        enable_select=False,
                        enable_double_click=False)
     self.label.text_color = ui_theme.get_color("menu_font")
     self.dropbutton = DisableButton(
         (ui_theme.get_pixbuf("combo/dropbutton_normal.png"),
          ui_theme.get_pixbuf("combo/dropbutton_hover.png"),
          ui_theme.get_pixbuf("combo/dropbutton_press.png"),
          ui_theme.get_pixbuf("combo/dropbutton_disable.png")),
         )
             
     self.align = gtk.Alignment()
     self.align.set(0.5, 0.5, 0.0, 0.0)
     self.align.set_padding(1, 1, 1 + self.label_padding_left, 1)
     
     self.pack_start(self.align, False, False)
     self.align.add(self.box)
     self.box.pack_start(self.label, False, False)
     self.box.pack_start(self.dropbutton, False, False)
     
     self.align.connect("expose-event", self.expose_combobox_frame)
     self.label.connect("button-press-event", self.click_drop_button)
     self.dropbutton.connect("button-press-event", self.click_drop_button)
     self.droplist.connect("item-selected", self.update_select_content)
     self.droplist.connect("key-release", lambda dl, s, o, i: self.emit("key-release", s, o, i))
     self.connect("key-press-event", self.key_press_combo)
     self.connect("key-release-event", self.key_release_combo)
     self.connect("focus-in-event", self.focus_in_combo)
     self.connect("focus-out-event", self.focus_out_combo)
     
     self.keymap = {
         "Home" : self.select_first_item,
         "End" : self.select_last_item,
         "Up" : self.select_prev_item,
         "Down" : self.select_next_item}
Beispiel #3
0
 def create_simple_button(self, name, callback=None):
     '''
     Internal function to create simple button.
     '''
     button = DisableButton(
         (ui_theme.get_pixbuf("spin/spin_arrow_%s_normal.png" % name),
          ui_theme.get_pixbuf("spin/spin_arrow_%s_hover.png" % name),
          ui_theme.get_pixbuf("spin/spin_arrow_%s_press.png" % name),
          ui_theme.get_pixbuf("spin/spin_arrow_%s_disable.png" % name)), )
     if callback:
         button.connect("button-press-event", callback)
         button.connect("button-release-event", self.handle_key_release)
     return button
Beispiel #4
0
    def __init__(self,
                 items=[],
                 droplist_height=None,
                 select_index=0,
                 max_width=None,
                 fixed_width=None,
                 min_width = 120,
                 min_height = 100,
                 editable=False,
                 ):
        '''
        Initialize ComboBox class.

        @param items: Init item list, default is empty list.
        @param droplist_height: The height of droplist, default is None that droplist's height will calculate with items' height automatically.
        @param select_index: Init index of selected item, default is 0.
        @param max_width: Maximum width of combobox, default is None.
        @param fixed_width: Fixed width of combobox, after you set this value combobox won't care the width of droplist and items, default is None.
        @param min_width: Minimum width of combobox, default is 120 pixels.
        @param min_height: Minimum height of combobox, default is 100 pixels.
        @param editable: Set True to make combobox can edit, default is False.
        '''
        gtk.VBox.__init__(self)
        self.set_can_focus(True)

        # Init variables.
        self.focus_flag = False
        self.select_index = select_index
        self.editable = editable
        if self.editable:
            self.padding_x = 0
        else:
            self.padding_x = 5

        self.combo_list = ComboList(min_width=min_width,
                                    max_width=max_width,
                                    fixed_width=fixed_width,
                                    min_height=min_height,
                                    max_height=droplist_height)

        self.drop_button = DisableButton(
            (ui_theme.get_pixbuf("combo/dropbutton_normal.png"),
             ui_theme.get_pixbuf("combo/dropbutton_hover.png"),
             ui_theme.get_pixbuf("combo/dropbutton_press.png"),
             ui_theme.get_pixbuf("combo/dropbutton_disable.png")),
            )
        self.drop_button_width = ui_theme.get_pixbuf("combo/dropbutton_normal.png").get_pixbuf().get_width()
        self.panel_align = gtk.Alignment()
        self.panel_align.set(0.5, 0.5, 0.0, 0.0)

        if self.editable:
            self.label = Entry()
        else:
            self.label = Label("", enable_select=False, enable_double_click=False)

            self.label.connect("button-press-event", self.on_drop_button_press)
            self.panel_align.set_padding(0, 0, self.padding_x, 0)

        self.panel_align.add(self.label)

        # Init items.
        self.add_items(items)

        # set selected index
        if len(items) > 0:
            self.set_select_index(select_index)

        hbox = gtk.HBox()
        hbox.pack_start(self.panel_align, True, False)
        hbox.pack_start(self.drop_button, False, False)
        box_align = gtk.Alignment()
        box_align.set(0.5, 0.5, 0.0, 0.0)
        box_align.add(hbox)
        self.add(box_align)

        # Connect signals.
        box_align.connect("expose-event", self.on_expose_combo_frame)
        self.drop_button.connect("button-press-event", self.on_drop_button_press)
        self.connect("focus-in-event", self.on_focus_in_combo)
        self.connect("focus-out-event", self.on_focus_out_combo)
        self.combo_list.treeview.connect("button-press-item", self.on_combo_single_click)
Beispiel #5
0
class ComboBox(gtk.VBox):
    '''
    ComboBox class.

    @undocumented: set_size_request
    @undocumented: auto_set_size
    @undocumented: on_drop_button_press
    @undocumented: on_combo_single_click
    @undocumented: on_focus_in_combo
    @undocumented: on_focus_out_combo
    @undocumented: items
    @undocumented: on_expose_combo_frame
    '''

    __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=[],
                 droplist_height=None,
                 select_index=0,
                 max_width=None,
                 fixed_width=None,
                 min_width = 120,
                 min_height = 100,
                 editable=False,
                 ):
        '''
        Initialize ComboBox class.

        @param items: Init item list, default is empty list.
        @param droplist_height: The height of droplist, default is None that droplist's height will calculate with items' height automatically.
        @param select_index: Init index of selected item, default is 0.
        @param max_width: Maximum width of combobox, default is None.
        @param fixed_width: Fixed width of combobox, after you set this value combobox won't care the width of droplist and items, default is None.
        @param min_width: Minimum width of combobox, default is 120 pixels.
        @param min_height: Minimum height of combobox, default is 100 pixels.
        @param editable: Set True to make combobox can edit, default is False.
        '''
        gtk.VBox.__init__(self)
        self.set_can_focus(True)

        # Init variables.
        self.focus_flag = False
        self.select_index = select_index
        self.editable = editable
        if self.editable:
            self.padding_x = 0
        else:
            self.padding_x = 5

        self.combo_list = ComboList(min_width=min_width,
                                    max_width=max_width,
                                    fixed_width=fixed_width,
                                    min_height=min_height,
                                    max_height=droplist_height)

        self.drop_button = DisableButton(
            (ui_theme.get_pixbuf("combo/dropbutton_normal.png"),
             ui_theme.get_pixbuf("combo/dropbutton_hover.png"),
             ui_theme.get_pixbuf("combo/dropbutton_press.png"),
             ui_theme.get_pixbuf("combo/dropbutton_disable.png")),
            )
        self.drop_button_width = ui_theme.get_pixbuf("combo/dropbutton_normal.png").get_pixbuf().get_width()
        self.panel_align = gtk.Alignment()
        self.panel_align.set(0.5, 0.5, 0.0, 0.0)

        if self.editable:
            self.label = Entry()
        else:
            self.label = Label("", enable_select=False, enable_double_click=False)

            self.label.connect("button-press-event", self.on_drop_button_press)
            self.panel_align.set_padding(0, 0, self.padding_x, 0)

        self.panel_align.add(self.label)

        # Init items.
        self.add_items(items)

        # set selected index
        if len(items) > 0:
            self.set_select_index(select_index)

        hbox = gtk.HBox()
        hbox.pack_start(self.panel_align, True, False)
        hbox.pack_start(self.drop_button, False, False)
        box_align = gtk.Alignment()
        box_align.set(0.5, 0.5, 0.0, 0.0)
        box_align.add(hbox)
        self.add(box_align)

        # Connect signals.
        box_align.connect("expose-event", self.on_expose_combo_frame)
        self.drop_button.connect("button-press-event", self.on_drop_button_press)
        self.connect("focus-in-event", self.on_focus_in_combo)
        self.connect("focus-out-event", self.on_focus_out_combo)
        self.combo_list.treeview.connect("button-press-item", self.on_combo_single_click)

    def set_size_request(self, width, height):
        pass

    def auto_set_size(self):
        valid_width = self.combo_list.get_adjust_width()
        remained_width = valid_width - self.drop_button_width - self.padding_x
        if self.editable:
            self.label.set_size_request(remained_width, -1)
        else:
            self.label.set_fixed_width(remained_width)
        self.combo_list.auto_set_size()

    def add_items(self,
                  items,
                  select_index=0,
                  pos=None,
                  clear_first=True,
                  ):
        '''
        Add items with given index.

        @param items: Item list that need add is combo box.
        @param select_index: The index of select item, default is 0.
        @param pos: Position to insert, except you specified index, items will insert at end by default.
        @param clear_first: Whether clear existing items before insert anymore, default is True.
        '''
        # Init combo widgets.
        if clear_first:
            self.combo_list.treeview.clear()
        combo_items = [ComboTextItem(item[0], item[1]) for item in items]
        self.combo_list.treeview.add_items(combo_items, insert_pos=pos)
        self.auto_set_size()
        self.set_select_index(select_index)

    def on_drop_button_press(self, widget, event):

        self.combo_list.hover_select_item()
        height = self.allocation.height
        x, y = self.window.get_root_origin()

        if self.combo_list.get_visible():
            self.combo_list.hide()
        else:
            wx, wy = int(event.x), int(event.y)
            (offset_x, offset_y) = widget.translate_coordinates(self, 0, 0)
            (_, px, py, modifier) = widget.get_display().get_pointer()
            droplist_x, droplist_y = px - wx - offset_x - 1, py - wy - offset_y + height - 1
            self.combo_list.show((droplist_x, droplist_y), (0, -height))

    def on_combo_single_click(self, widget, item, column, x, y):
        self.label.set_text(item.title)
        self.combo_list.reset_status()
        if item:
            index = self.combo_list.get_select_index()
            self.combo_list.hide_self()
            self.emit("item-selected", item.title, item.item_value, index)

    def on_focus_in_combo(self, widget, event):
        self.focus_flag = True
        self.queue_draw()

    def on_focus_out_combo(self, widget, event):
        self.focus_flag = False
        self.queue_draw()

    def set_select_index(self, item_index):
        '''
        Set select item with given index.

        @param item_index: The index of selected item.
        '''
        if 0 <= item_index < len(self.items):
            self.combo_list.set_select_index(item_index)
            self.label.set_text(self.items[item_index].title)

    @property
    def items(self):
        return self.combo_list.items

    def get_item_with_index(self, item_index):
        '''
        Get item with given index.

        @param item_index: The index of item that you want get.
        @return: Return item with given index, return None if given index is invalid.
        '''
        if 0 <= item_index < len(self.items):
            item = self.items[item_index]
            return (item.title, item.item_value)
        else:
            return None

    def get_current_item(self):
        '''
        Get current selected item.

        @return: Return current selected item.
        '''
        return self.get_item_with_index(self.get_select_index())

    def get_select_index(self):
        '''
        Get index of select item.

        @return: Return index of selected item.
        '''
        return self.combo_list.get_select_index()

    def set_sensitive(self, sensitive):
        super(ComboBox, self).set_sensitive(sensitive)
        self.label.set_sensitive(sensitive)

    def on_expose_combo_frame(self, widget, event):
        # Init.
        cr = widget.window.cairo_create()
        rect = widget.allocation

        # Draw frame.
        with cairo_disable_antialias(cr):
            cr.set_line_width(1)
            if self.get_sensitive():
                cr.set_source_rgb(*color_hex_to_cairo(ui_theme.get_color("combo_entry_frame").get_color()))
            else:
                cr.set_source_rgb(*color_hex_to_cairo(ui_theme.get_color("disable_frame").get_color()))
            cr.rectangle(rect.x, rect.y, rect.width, rect.height)
            cr.stroke()

            if self.focus_flag:
                color = (ui_theme.get_color("combo_entry_select_background").get_color(), 0.9)
                cr.set_source_rgba(*alpha_color_hex_to_cairo(color))
                cr.rectangle(rect.x, rect.y, rect.width - 1 - self.drop_button_width, rect.height - 1)
                cr.fill()
                cr.set_source_rgba(*alpha_color_hex_to_cairo((ui_theme.get_color("combo_entry_background").get_color(), 0.9)))
                cr.rectangle(rect.x + rect.width - 1 - self.drop_button_width, rect.y, self.drop_button_width, rect.height - 1)
                cr.fill()
            else:
                cr.set_source_rgba(*alpha_color_hex_to_cairo((ui_theme.get_color("combo_entry_background").get_color(), 0.9)))
                cr.rectangle(rect.x, rect.y, rect.width - 1, rect.height - 1)
                cr.fill()

        # Propagate expose to children.
        propagate_expose(widget, event)

        return True
Beispiel #6
0
class ComboBox(gtk.VBox):
    '''Combo box.'''
	
    __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, droplist_height=None, select_index=0, max_width=None):
        '''Init combo box.'''
        # Init.
        gtk.VBox.__init__(self)
        self.set_can_focus(True)
        self.items = items
        self.droplist_height = droplist_height
        self.select_index = select_index
        self.focus_flag = False
        
        self.droplist = Droplist(self.items, max_width=max_width)
        if self.droplist_height:
            self.droplist.set_size_request(-1, self.droplist_height)
        self.width = self.droplist.get_droplist_width() 
        self.height = 22
        self.label_padding_left = 6
        self.box = gtk.HBox()
        self.dropbutton_width = ui_theme.get_pixbuf("combo/dropbutton_normal.png").get_pixbuf().get_width()
        self.label = Label(self.items[select_index][0], 
                           label_width=self.width - self.dropbutton_width - 1 - self.label_padding_left,
                           enable_select=False,
                           enable_double_click=False)
        self.label.text_color = ui_theme.get_color("menu_font")
        self.dropbutton = DisableButton(
            (ui_theme.get_pixbuf("combo/dropbutton_normal.png"),
             ui_theme.get_pixbuf("combo/dropbutton_hover.png"),
             ui_theme.get_pixbuf("combo/dropbutton_press.png"),
             ui_theme.get_pixbuf("combo/dropbutton_disable.png")),
            )
                
        self.align = gtk.Alignment()
        self.align.set(0.5, 0.5, 0.0, 0.0)
        self.align.set_padding(1, 1, 1 + self.label_padding_left, 1)
        
        self.pack_start(self.align, False, False)
        self.align.add(self.box)
        self.box.pack_start(self.label, False, False)
        self.box.pack_start(self.dropbutton, False, False)
        
        self.align.connect("expose-event", self.expose_combobox_frame)
        self.label.connect("button-press-event", self.click_drop_button)
        self.dropbutton.connect("button-press-event", self.click_drop_button)
        self.droplist.connect("item-selected", self.update_select_content)
        self.droplist.connect("key-release", lambda dl, s, o, i: self.emit("key-release", s, o, i))
        self.connect("key-press-event", self.key_press_combo)
        self.connect("key-release-event", self.key_release_combo)
        self.connect("focus-in-event", self.focus_in_combo)
        self.connect("focus-out-event", self.focus_out_combo)
        
        self.keymap = {
            "Home" : self.select_first_item,
            "End" : self.select_last_item,
            "Up" : self.select_prev_item,
            "Down" : self.select_next_item}
        
    def focus_in_combo(self, widget, event):
        '''Focus in combo.'''
        self.focus_flag = True
        self.label.text_color = ui_theme.get_color("menu_select_font")

        self.queue_draw()
        
    def focus_out_combo(self, widget, event):
        '''Focus out combo.'''
        self.focus_flag = False        
        self.label.text_color = ui_theme.get_color("menu_font")
            
        self.queue_draw()
        
    def click_drop_button(self, *args):
        '''Click drop button.'''
        if self.droplist.get_visible():
            self.droplist.hide()
        else:
            (align_x, align_y) = get_widget_root_coordinate(self.align, WIDGET_POS_BOTTOM_LEFT)
            self.droplist.show(
                (align_x - 1, align_y - 1),
                (0, -self.height + 1))
            
            self.droplist.item_select_index = self.select_index
            self.droplist.active_item()
            self.droplist.scroll_page_to_select_item()
            
        self.queue_draw()    
        
    def select_first_item(self):
        '''Select first item.'''
        if len(self.droplist.droplist_items) > 0:
            first_index = self.droplist.get_first_index()
            if first_index != None:
                self.droplist.item_select_index = first_index
                self.droplist.active_item()
                self.droplist.droplist_items[self.droplist.item_select_index].wrap_droplist_clicked_action()
    
    def select_last_item(self):
        '''Select last item.'''
        if len(self.droplist.droplist_items) > 0:
            last_index = self.droplist.get_last_index()
            if last_index != None:
                self.droplist.item_select_index = last_index
                self.droplist.active_item()
                self.droplist.droplist_items[self.droplist.item_select_index].wrap_droplist_clicked_action()
    
    def select_prev_item(self):
        '''Select preview item.'''
        if len(self.droplist.droplist_items) > 0:
            prev_index = self.droplist.get_prev_index()
            if prev_index != None:
                self.droplist.item_select_index = prev_index
                self.droplist.active_item()
                self.droplist.droplist_items[self.droplist.item_select_index].wrap_droplist_clicked_action()
    
    def select_next_item(self):
        '''Select next item.'''
        if len(self.droplist.droplist_items) > 0:
            next_index = self.droplist.get_next_index()
            if next_index != None:
                self.droplist.item_select_index = next_index
                self.droplist.active_item()
                self.droplist.droplist_items[self.droplist.item_select_index].wrap_droplist_clicked_action()
        
    def key_press_combo(self, widget, event):
        '''Key press combo.'''
        if not self.droplist.get_visible():
            key_name = get_keyevent_name(event)
            if self.keymap.has_key(key_name):
                self.keymap[key_name]()
            
            return True     
        
    def set_select_index(self, item_index):
        '''Set select index.'''
        if 0 <= item_index < len(self.items):
            item = self.items[item_index]
            if item:
                self.select_index = item_index
                self.label.set_text(item[0])
                
    def get_item_with_index(self, item_index):
        '''Get item with index.'''
        if 0 <= item_index < len(self.items):
            return self.items[item_index]                
        else:
            return None
        
    def get_current_item(self):
        '''Get current item.'''
        return self.get_item_with_index(self.select_index)
                
    def key_release_combo(self, widget, event):
        '''Handle key release.'''
        self.emit("key-release", 
                  self.items[self.select_index][0],
                  self.items[self.select_index][1],
                  self.select_index)    
    
    def update_select_content(self, droplist, item_content, item_value, item_index):
        '''Update select content.'''
        self.select_index = item_index
        self.label.set_text(item_content)
        
        self.emit("item-selected", item_content, item_value, item_index)
        
        self.grab_focus()
        
        self.queue_draw()
        
    def set_sensitive(self, sensitive):
        super(ComboBox, self).set_sensitive(sensitive)
        self.label.set_sensitive(sensitive)
        self.dropbutton.set_sensitive(sensitive)
            
    def expose_combobox_frame(self, widget, event):
        '''Expose combo box frame.'''
        # Init.
        cr = widget.window.cairo_create()
        rect = widget.allocation
        
        # Draw frame.
        with cairo_disable_antialias(cr):
            cr.set_line_width(1)
            if self.get_sensitive():
                cr.set_source_rgb(*color_hex_to_cairo(ui_theme.get_color("combo_entry_frame").get_color()))
            else:
                cr.set_source_rgb(*color_hex_to_cairo(ui_theme.get_color("disable_frame").get_color()))
            cr.rectangle(rect.x, rect.y, rect.width, rect.height)
            cr.stroke()
            
            if self.focus_flag:
                cr.set_source_rgba(*alpha_color_hex_to_cairo((ui_theme.get_color("combo_entry_select_background").get_color(), 0.9)))
                cr.rectangle(rect.x, rect.y, rect.width - 1 - self.dropbutton_width, rect.height - 1)
                cr.fill()
                
                cr.set_source_rgba(*alpha_color_hex_to_cairo((ui_theme.get_color("combo_entry_background").get_color(), 0.9)))
                cr.rectangle(rect.x + rect.width - 1 - self.dropbutton_width, rect.y, self.dropbutton_width, rect.height - 1)
                cr.fill()
            else:
                cr.set_source_rgba(*alpha_color_hex_to_cairo((ui_theme.get_color("combo_entry_background").get_color(), 0.9)))
                cr.rectangle(rect.x, rect.y, rect.width - 1, rect.height - 1)
                cr.fill()
        
        # Propagate expose to children.
        propagate_expose(widget, event)
        
        return True
Beispiel #7
0
    def __init__(
        self,
        items=[],
        droplist_height=None,
        select_index=0,
        max_width=None,
        fixed_width=None,
        min_width=120,
        min_height=100,
        editable=False,
    ):
        '''
        Initialize ComboBox class.

        @param items: Init item list, default is empty list.
        @param droplist_height: The height of droplist, default is None that droplist's height will calculate with items' height automatically.
        @param select_index: Init index of selected item, default is 0.
        @param max_width: Maximum width of combobox, default is None.
        @param fixed_width: Fixed width of combobox, after you set this value combobox won't care the width of droplist and items, default is None.
        @param min_width: Minimum width of combobox, default is 120 pixels.
        @param min_height: Minimum height of combobox, default is 100 pixels.
        @param editable: Set True to make combobox can edit, default is False.
        '''
        gtk.VBox.__init__(self)
        self.set_can_focus(True)

        # Init variables.
        self.focus_flag = False
        self.select_index = select_index
        self.editable = editable
        if self.editable:
            self.padding_x = 0
        else:
            self.padding_x = 5

        self.combo_list = ComboList(min_width=min_width,
                                    max_width=max_width,
                                    fixed_width=fixed_width,
                                    min_height=min_height,
                                    max_height=droplist_height)

        self.drop_button = DisableButton(
            (ui_theme.get_pixbuf("combo/dropbutton_normal.png"),
             ui_theme.get_pixbuf("combo/dropbutton_hover.png"),
             ui_theme.get_pixbuf("combo/dropbutton_press.png"),
             ui_theme.get_pixbuf("combo/dropbutton_disable.png")), )
        self.drop_button_width = ui_theme.get_pixbuf(
            "combo/dropbutton_normal.png").get_pixbuf().get_width()
        self.panel_align = gtk.Alignment()
        self.panel_align.set(0.5, 0.5, 0.0, 0.0)

        if self.editable:
            self.label = Entry()
        else:
            self.label = Label("",
                               enable_select=False,
                               enable_double_click=False)

            self.label.connect("button-press-event", self.on_drop_button_press)
            self.panel_align.set_padding(0, 0, self.padding_x, 0)

        self.panel_align.add(self.label)

        # Init items.
        self.add_items(items)

        # set selected index
        if len(items) > 0:
            self.set_select_index(select_index)

        hbox = gtk.HBox()
        hbox.pack_start(self.panel_align, True, False)
        hbox.pack_start(self.drop_button, False, False)
        box_align = gtk.Alignment()
        box_align.set(0.5, 0.5, 0.0, 0.0)
        box_align.add(hbox)
        self.add(box_align)

        # Connect signals.
        box_align.connect("expose-event", self.on_expose_combo_frame)
        self.drop_button.connect("button-press-event",
                                 self.on_drop_button_press)
        self.connect("focus-in-event", self.on_focus_in_combo)
        self.connect("focus-out-event", self.on_focus_out_combo)
        self.combo_list.treeview.connect("button-press-item",
                                         self.on_combo_single_click)
Beispiel #8
0
class ComboBox(gtk.VBox):
    '''
    ComboBox class.

    @undocumented: set_size_request
    @undocumented: auto_set_size
    @undocumented: on_drop_button_press
    @undocumented: on_combo_single_click
    @undocumented: on_focus_in_combo
    @undocumented: on_focus_out_combo
    @undocumented: items
    @undocumented: on_expose_combo_frame
    '''

    __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=[],
        droplist_height=None,
        select_index=0,
        max_width=None,
        fixed_width=None,
        min_width=120,
        min_height=100,
        editable=False,
    ):
        '''
        Initialize ComboBox class.

        @param items: Init item list, default is empty list.
        @param droplist_height: The height of droplist, default is None that droplist's height will calculate with items' height automatically.
        @param select_index: Init index of selected item, default is 0.
        @param max_width: Maximum width of combobox, default is None.
        @param fixed_width: Fixed width of combobox, after you set this value combobox won't care the width of droplist and items, default is None.
        @param min_width: Minimum width of combobox, default is 120 pixels.
        @param min_height: Minimum height of combobox, default is 100 pixels.
        @param editable: Set True to make combobox can edit, default is False.
        '''
        gtk.VBox.__init__(self)
        self.set_can_focus(True)

        # Init variables.
        self.focus_flag = False
        self.select_index = select_index
        self.editable = editable
        if self.editable:
            self.padding_x = 0
        else:
            self.padding_x = 5

        self.combo_list = ComboList(min_width=min_width,
                                    max_width=max_width,
                                    fixed_width=fixed_width,
                                    min_height=min_height,
                                    max_height=droplist_height)

        self.drop_button = DisableButton(
            (ui_theme.get_pixbuf("combo/dropbutton_normal.png"),
             ui_theme.get_pixbuf("combo/dropbutton_hover.png"),
             ui_theme.get_pixbuf("combo/dropbutton_press.png"),
             ui_theme.get_pixbuf("combo/dropbutton_disable.png")), )
        self.drop_button_width = ui_theme.get_pixbuf(
            "combo/dropbutton_normal.png").get_pixbuf().get_width()
        self.panel_align = gtk.Alignment()
        self.panel_align.set(0.5, 0.5, 0.0, 0.0)

        if self.editable:
            self.label = Entry()
        else:
            self.label = Label("",
                               enable_select=False,
                               enable_double_click=False)

            self.label.connect("button-press-event", self.on_drop_button_press)
            self.panel_align.set_padding(0, 0, self.padding_x, 0)

        self.panel_align.add(self.label)

        # Init items.
        self.add_items(items)

        # set selected index
        if len(items) > 0:
            self.set_select_index(select_index)

        hbox = gtk.HBox()
        hbox.pack_start(self.panel_align, True, False)
        hbox.pack_start(self.drop_button, False, False)
        box_align = gtk.Alignment()
        box_align.set(0.5, 0.5, 0.0, 0.0)
        box_align.add(hbox)
        self.add(box_align)

        # Connect signals.
        box_align.connect("expose-event", self.on_expose_combo_frame)
        self.drop_button.connect("button-press-event",
                                 self.on_drop_button_press)
        self.connect("focus-in-event", self.on_focus_in_combo)
        self.connect("focus-out-event", self.on_focus_out_combo)
        self.combo_list.treeview.connect("button-press-item",
                                         self.on_combo_single_click)

    def set_size_request(self, width, height):
        pass

    def auto_set_size(self):
        valid_width = self.combo_list.get_adjust_width()
        remained_width = valid_width - self.drop_button_width - self.padding_x
        if self.editable:
            self.label.set_size_request(remained_width, -1)
        else:
            self.label.set_fixed_width(remained_width)
        self.combo_list.auto_set_size()

    def add_items(
        self,
        items,
        select_index=0,
        pos=None,
        clear_first=True,
    ):
        '''
        Add items with given index.

        @param items: Item list that need add is combo box.
        @param select_index: The index of select item, default is 0.
        @param pos: Position to insert, except you specified index, items will insert at end by default.
        @param clear_first: Whether clear existing items before insert anymore, default is True.
        '''
        # Init combo widgets.
        if clear_first:
            self.combo_list.treeview.clear()
        combo_items = [ComboTextItem(item[0], item[1]) for item in items]
        self.combo_list.treeview.add_items(combo_items, insert_pos=pos)
        self.auto_set_size()
        self.set_select_index(select_index)

    def on_drop_button_press(self, widget, event):

        self.combo_list.hover_select_item()
        height = self.allocation.height
        x, y = self.window.get_root_origin()

        if self.combo_list.get_visible():
            self.combo_list.hide()
        else:
            wx, wy = int(event.x), int(event.y)
            (offset_x, offset_y) = widget.translate_coordinates(self, 0, 0)
            (_, px, py, modifier) = widget.get_display().get_pointer()
            droplist_x, droplist_y = px - wx - offset_x - 1, py - wy - offset_y + height - 1
            self.combo_list.show((droplist_x, droplist_y), (0, -height))

    def on_combo_single_click(self, widget, item, column, x, y):
        self.label.set_text(item.title)
        self.combo_list.reset_status()
        if item:
            index = self.combo_list.get_select_index()
            self.combo_list.hide_self()
            self.emit("item-selected", item.title, item.item_value, index)

    def on_focus_in_combo(self, widget, event):
        self.focus_flag = True
        self.queue_draw()

    def on_focus_out_combo(self, widget, event):
        self.focus_flag = False
        self.queue_draw()

    def set_select_index(self, item_index):
        '''
        Set select item with given index.

        @param item_index: The index of selected item.
        '''
        if 0 <= item_index < len(self.items):
            self.combo_list.set_select_index(item_index)
            self.label.set_text(self.items[item_index].title)

    @property
    def items(self):
        return self.combo_list.items

    def get_item_with_index(self, item_index):
        '''
        Get item with given index.

        @param item_index: The index of item that you want get.
        @return: Return item with given index, return None if given index is invalid.
        '''
        if 0 <= item_index < len(self.items):
            item = self.items[item_index]
            return (item.title, item.item_value)
        else:
            return None

    def get_current_item(self):
        '''
        Get current selected item.

        @return: Return current selected item.
        '''
        return self.get_item_with_index(self.get_select_index())

    def get_select_index(self):
        '''
        Get index of select item.

        @return: Return index of selected item.
        '''
        return self.combo_list.get_select_index()

    def set_sensitive(self, sensitive):
        super(ComboBox, self).set_sensitive(sensitive)
        self.label.set_sensitive(sensitive)

    def on_expose_combo_frame(self, widget, event):
        # Init.
        cr = widget.window.cairo_create()
        rect = widget.allocation

        # Draw frame.
        with cairo_disable_antialias(cr):
            cr.set_line_width(1)
            if self.get_sensitive():
                cr.set_source_rgb(*color_hex_to_cairo(
                    ui_theme.get_color("combo_entry_frame").get_color()))
            else:
                cr.set_source_rgb(*color_hex_to_cairo(
                    ui_theme.get_color("disable_frame").get_color()))
            cr.rectangle(rect.x, rect.y, rect.width, rect.height)
            cr.stroke()

            if self.focus_flag:
                color = (ui_theme.get_color(
                    "combo_entry_select_background").get_color(), 0.9)
                cr.set_source_rgba(*alpha_color_hex_to_cairo(color))
                cr.rectangle(rect.x, rect.y,
                             rect.width - 1 - self.drop_button_width,
                             rect.height - 1)
                cr.fill()
                cr.set_source_rgba(*alpha_color_hex_to_cairo((
                    ui_theme.get_color("combo_entry_background").get_color(),
                    0.9)))
                cr.rectangle(rect.x + rect.width - 1 - self.drop_button_width,
                             rect.y, self.drop_button_width, rect.height - 1)
                cr.fill()
            else:
                cr.set_source_rgba(*alpha_color_hex_to_cairo((
                    ui_theme.get_color("combo_entry_background").get_color(),
                    0.9)))
                cr.rectangle(rect.x, rect.y, rect.width - 1, rect.height - 1)
                cr.fill()

        # Propagate expose to children.
        propagate_expose(widget, event)

        return True