예제 #1
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
예제 #2
0
파일: spin.py 프로젝트: masums/deepin-ui
class TimeSpinBox(gtk.VBox):
    '''
    TimeSpinBox class.

    @undocumented: value_changed
    @undocumented: size_change_cb
    @undocumented: press_increase_button
    @undocumented: press_decrease_button
    @undocumented: handle_key_release
    @undocumented: expose_time_spin
    @undocumented: create_simple_button
    '''

    SET_NONE = 0
    SET_HOUR = 1
    SET_MIN = 2
    SET_SEC = 3

    __gsignals__ = {
        "value-changed":
        (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
         (gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_INT)),
        "key-release":
        (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE,
         (gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_INT)),
    }

    def __init__(
        self,
        width=95,
        height=22,
        padding_x=5,
        is_24hour=True,
    ):
        '''
        Initialize TimeSpinBox class.

        @param width: The width of TimeSpinBox, default is 95 pixels.
        @param height: The height of TimeSpinBox, default is 22 pixels.
        @param padding_x: The padding x of TimeSpinBox, default is 5 pixels.
        @param is_24hour: Whether use 24 hours format, default is True.
        '''
        gtk.VBox.__init__(self)

        self.set_time = self.SET_NONE
        self.set_time_bg_color = "#DCDCDC"
        self.time_width = 0
        self.time_comma_width = 0
        self.__24hour = is_24hour
        self.__pressed_button = False

        self.hour_value = time.localtime().tm_hour
        self.min_value = time.localtime().tm_min
        self.sec_value = time.localtime().tm_sec

        # Init.
        self.width = width
        self.height = height
        self.padding_x = padding_x
        self.arrow_button_width = 19
        self.background_color = ui_theme.get_alpha_color(
            "text_entry_background")
        self.acme_color = ui_theme.get_alpha_color("text_entry_acme")
        self.point_color = ui_theme.get_alpha_color("text_entry_point")
        self.frame_point_color = ui_theme.get_alpha_color(
            "text_entry_frame_point")
        self.frame_color = ui_theme.get_alpha_color("text_entry_frame")

        # Widget.
        arrow_up_button = self.create_simple_button("up",
                                                    self.press_increase_button)
        arrow_down_button = self.create_simple_button(
            "down", self.press_decrease_button)
        button_box = gtk.VBox()
        button_box.pack_start(arrow_up_button, False, False)
        button_box.pack_start(arrow_down_button, False, False)
        self.time_label = Label()

        self.main_align = gtk.Alignment()
        self.main_align.set(0.5, 0.5, 0, 0)
        hbox = gtk.HBox()
        hbox.pack_start(self.time_label, False, False)
        hbox.pack_end(button_box, False, False)
        hbox_align = gtk.Alignment()
        hbox_align.set(0.5, 0.5, 1.0, 1.0)
        hbox_align.set_padding(0, 1, 0, 0)
        hbox_align.add(hbox)
        self.main_align.add(hbox_align)
        self.pack_start(self.main_align, False, False)

        # Signals.
        self.connect("size-allocate", self.size_change_cb)
        self.time_label.connect("button-press-event", self.__time_label_press)
        self.main_align.connect("expose-event", self.expose_time_spin)
        SecondThread(self).start()

    def get_24hour(self):
        '''
        Get whether use 24 hour format.

        @return: Return True if is use 24 hour format.
        '''
        return self.__24hour

    def set_24hour(self, value):
        '''
        Set whether use 24 hour format.

        @param value: Set as True to use 24 hour format.
        '''
        self.__24hour = value
        self.queue_draw()

    def __time_label_press(self, widget, event):
        (self.time_width, text_height) = get_content_size("12")
        (self.time_comma_width, text_comma_height) = get_content_size(" : ")

        if event.x < self.padding_x + self.time_width:
            self.set_time = self.SET_HOUR
            return

        if event.x > self.padding_x + self.time_width and event.x < self.padding_x + (
                self.time_width + self.time_comma_width) * 2:
            self.set_time = self.SET_MIN
            return

        if event.x > self.padding_x + self.time_width + self.time_comma_width * 2:
            self.set_time = self.SET_SEC
            return

    def value_changed(self):
        '''
        Emit `value-changed` signal.
        '''
        if self.__24hour:
            self.emit("value-changed", self.hour_value, self.min_value,
                      self.sec_value)
        else:
            if time.localtime().tm_hour <= 12:
                self.emit("value-changed", self.hour_value, self.min_value,
                          self.sec_value)
            else:
                self.emit("value-changed", self.hour_value + 12,
                          self.min_value, self.sec_value)

    def size_change_cb(self, widget, rect):
        '''
        Internal callback for `size-allocate` signal.
        '''
        if rect.width > self.width:
            self.width = rect.width

        self.set_size_request(self.width, self.height)
        self.time_label.set_size_request(self.width - self.arrow_button_width,
                                         self.height - 2)

    def press_increase_button(self, widget, event):
        '''
        Internal callback when user press increase arrow.
        '''
        if self.set_time == self.SET_HOUR:
            self.__pressed_button = True
            self.hour_value += 1
            if self.__24hour:
                if self.hour_value >= 24:
                    self.hour_value = 0
            else:
                if self.hour_value >= 12:
                    self.hour_value = 1
        elif self.set_time == self.SET_MIN:
            self.__pressed_button = True
            self.min_value += 1
            if self.min_value >= 60:
                self.min_value = 0
        elif self.set_time == self.SET_SEC:
            self.__pressed_button = True
            self.sec_value += 1
            if self.sec_value >= 60:
                self.sec_value = 0
        else:
            pass

        self.value_changed()
        self.queue_draw()

    def press_decrease_button(self, widget, event):
        '''
        Internal callback when user press decrease arrow.
        '''
        if self.set_time == self.SET_HOUR:
            self.__pressed_button = True
            self.hour_value -= 1
            if self.__24hour:
                if self.hour_value < 0:
                    self.hour_value = 23
            else:
                if self.hour_value < 0:
                    self.hour_value = 11
        elif self.set_time == self.SET_MIN:
            self.__pressed_button = True
            self.min_value -= 1
            if self.min_value < 0:
                self.min_value = 59
        elif self.set_time == self.SET_SEC:
            self.__pressed_button = True
            self.sec_value -= 1
            if self.sec_value < 0:
                self.sec_value = 59
        else:
            pass

        self.value_changed()
        self.queue_draw()

    def handle_key_release(self, widget, event):
        '''
        Internal callback for `key-release-event` signal.
        '''
        self.emit("key-release", self.hour_value, self.min_value,
                  self.sec_value)

    def expose_time_spin(self, widget, event):
        '''
        Internal callback for `expose-event` signal.
        '''
        # Init.
        cr = widget.window.cairo_create()
        rect = widget.allocation
        x, y, w, h = rect.x, rect.y, rect.width, rect.height

        # Draw frame.
        with cairo_disable_antialias(cr):
            cr.set_line_width(1)
            if widget.state == gtk.STATE_INSENSITIVE:
                cr.set_source_rgb(*color_hex_to_cairo(
                    ui_theme.get_color("disable_frame").get_color()))
            else:
                cr.set_source_rgb(*color_hex_to_cairo(
                    ui_theme.get_color("combo_entry_frame").get_color()))
            cr.rectangle(x, y, w, h)
            cr.stroke()

            if widget.state == gtk.STATE_INSENSITIVE:
                cr.set_source_rgba(*alpha_color_hex_to_cairo((
                    ui_theme.get_color("disable_background").get_color(),
                    0.9)))
            else:
                cr.set_source_rgba(*alpha_color_hex_to_cairo((
                    ui_theme.get_color("combo_entry_background").get_color(),
                    0.9)))
            cr.rectangle(x, y, w - 1, h - 1)
            cr.fill()

        if self.set_time == self.SET_HOUR:
            cr.set_source_rgba(*color_hex_to_cairo(self.set_time_bg_color))
            cr.rectangle(x + self.padding_x, y, self.time_width, h)
            cr.fill()

        if self.set_time == self.SET_MIN:
            cr.set_source_rgba(*color_hex_to_cairo(self.set_time_bg_color))
            cr.rectangle(
                x + self.padding_x + self.time_width + self.time_comma_width,
                y, self.time_width, h)
            cr.fill()

        if self.set_time == self.SET_SEC:
            cr.set_source_rgba(*color_hex_to_cairo(self.set_time_bg_color))
            cr.rectangle(
                x + self.padding_x +
                (self.time_width + self.time_comma_width) * 2, y,
                self.time_width, h)
            cr.fill()

        if not self.__pressed_button:
            if self.__24hour:
                self.hour_value = time.localtime().tm_hour
            else:
                self.hour_value = int(time.strftime('%I'))
            self.min_value = time.localtime().tm_min
            self.sec_value = time.localtime().tm_sec

        draw_text(
            cr, "%02d : %02d : %02d" %
            (self.hour_value, self.min_value, self.sec_value),
            x + self.padding_x, y, w, h)

        propagate_expose(widget, event)

        return False

    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
예제 #3
0
파일: combo.py 프로젝트: netphi/deepin-ui
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
예제 #4
0
class TimeSpinBox(gtk.VBox):
    '''
    TimeSpinBox class.

    @undocumented: value_changed
    @undocumented: size_change_cb
    @undocumented: press_increase_button
    @undocumented: press_decrease_button
    @undocumented: handle_key_release
    @undocumented: expose_time_spin
    @undocumented: create_simple_button
    '''

    SET_NONE = 0
    SET_HOUR = 1
    SET_MIN = 2
    SET_SEC = 3

    __gsignals__ = {
        "value-changed" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_INT)),
        "key-release" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_INT)),
        }

    def __init__(self,
                 width=95,
                 height=22,
                 padding_x=5,
                 is_24hour=True,
                 ):
        '''
        Initialize TimeSpinBox class.

        @param width: The width of TimeSpinBox, default is 95 pixels.
        @param height: The height of TimeSpinBox, default is 22 pixels.
        @param padding_x: The padding x of TimeSpinBox, default is 5 pixels.
        @param is_24hour: Whether use 24 hours format, default is True.
        '''
        gtk.VBox.__init__(self)

        self.set_time = self.SET_NONE
        self.set_time_bg_color = "#DCDCDC"
        self.time_width = 0
        self.time_comma_width = 0
        self.__24hour = is_24hour
        self.__pressed_button = False

        self.hour_value = time.localtime().tm_hour
        self.min_value = time.localtime().tm_min
        self.sec_value = time.localtime().tm_sec

        # Init.
        self.width = width
        self.height = height
        self.padding_x = padding_x
        self.arrow_button_width = 19
        self.background_color = ui_theme.get_alpha_color("text_entry_background")
        self.acme_color = ui_theme.get_alpha_color("text_entry_acme")
        self.point_color = ui_theme.get_alpha_color("text_entry_point")
        self.frame_point_color = ui_theme.get_alpha_color("text_entry_frame_point")
        self.frame_color = ui_theme.get_alpha_color("text_entry_frame")

        # Widget.
        arrow_up_button = self.create_simple_button("up", self.press_increase_button)
        arrow_down_button = self.create_simple_button("down", self.press_decrease_button)
        button_box = gtk.VBox()
        button_box.pack_start(arrow_up_button, False, False)
        button_box.pack_start(arrow_down_button, False, False)
        self.time_label = Label()

        self.main_align = gtk.Alignment()
        self.main_align.set(0.5, 0.5, 0, 0)
        hbox = gtk.HBox()
        hbox.pack_start(self.time_label, False, False)
        hbox.pack_end(button_box, False, False)
        hbox_align = gtk.Alignment()
        hbox_align.set(0.5, 0.5, 1.0, 1.0)
        hbox_align.set_padding(0, 1, 0, 0)
        hbox_align.add(hbox)
        self.main_align.add(hbox_align)
        self.pack_start(self.main_align, False, False)

        # Signals.
        self.connect("size-allocate", self.size_change_cb)
        self.time_label.connect("button-press-event", self.__time_label_press)
        self.main_align.connect("expose-event", self.expose_time_spin)
        SecondThread(self).start()

    def get_24hour(self):
        '''
        Get whether use 24 hour format.

        @return: Return True if is use 24 hour format.
        '''
        return self.__24hour

    def set_24hour(self, value):
        '''
        Set whether use 24 hour format.

        @param value: Set as True to use 24 hour format.
        '''
        self.__24hour = value
        self.queue_draw()

    def __time_label_press(self, widget, event):
        (self.time_width, text_height) = get_content_size("12")
        (self.time_comma_width, text_comma_height) = get_content_size(" : ")

        if event.x < self.padding_x + self.time_width:
            self.set_time = self.SET_HOUR
            return

        if event.x > self.padding_x + self.time_width and event.x < self.padding_x + (self.time_width + self.time_comma_width) * 2:
            self.set_time = self.SET_MIN
            return

        if event.x > self.padding_x + self.time_width + self.time_comma_width * 2:
            self.set_time = self.SET_SEC
            return

    def value_changed(self):
        '''
        Emit `value-changed` signal.
        '''
        if self.__24hour:
            self.emit("value-changed", self.hour_value, self.min_value, self.sec_value)
        else:
            if time.localtime().tm_hour <= 12:
                self.emit("value-changed", self.hour_value, self.min_value, self.sec_value)
            else:
                self.emit("value-changed", self.hour_value + 12, self.min_value, self.sec_value)

    def size_change_cb(self, widget, rect):
        '''
        Internal callback for `size-allocate` signal.
        '''
        if rect.width > self.width:
            self.width = rect.width

        self.set_size_request(self.width, self.height)
        self.time_label.set_size_request(self.width - self.arrow_button_width, self.height - 2)

    def press_increase_button(self, widget, event):
        '''
        Internal callback when user press increase arrow.
        '''
        if self.set_time == self.SET_HOUR:
            self.__pressed_button = True
            self.hour_value += 1
            if self.__24hour:
                if self.hour_value >= 24:
                    self.hour_value = 0
            else:
                if self.hour_value >= 12:
                    self.hour_value = 1
        elif self.set_time == self.SET_MIN:
            self.__pressed_button = True
            self.min_value += 1
            if self.min_value >= 60:
                self.min_value = 0
        elif self.set_time == self.SET_SEC:
            self.__pressed_button = True
            self.sec_value += 1
            if self.sec_value >= 60:
                self.sec_value = 0
        else:
            pass

        self.value_changed()
        self.queue_draw()

    def press_decrease_button(self, widget, event):
        '''
        Internal callback when user press decrease arrow.
        '''
        if self.set_time == self.SET_HOUR:
            self.__pressed_button = True
            self.hour_value -= 1
            if self.__24hour:
                if self.hour_value < 0:
                    self.hour_value = 23
            else:
                if self.hour_value < 0:
                    self.hour_value = 11
        elif self.set_time == self.SET_MIN:
            self.__pressed_button = True
            self.min_value -= 1
            if self.min_value < 0:
                self.min_value = 59
        elif self.set_time == self.SET_SEC:
            self.__pressed_button = True
            self.sec_value -= 1
            if self.sec_value < 0:
                self.sec_value = 59
        else:
            pass

        self.value_changed()
        self.queue_draw()

    def handle_key_release(self, widget, event):
        '''
        Internal callback for `key-release-event` signal.
        '''
        self.emit("key-release", self.hour_value, self.min_value, self.sec_value)

    def expose_time_spin(self, widget, event):
        '''
        Internal callback for `expose-event` signal.
        '''
        # Init.
        cr = widget.window.cairo_create()
        rect = widget.allocation
        x, y, w, h = rect.x, rect.y, rect.width, rect.height

        # Draw frame.
        with cairo_disable_antialias(cr):
            cr.set_line_width(1)
            if widget.state == gtk.STATE_INSENSITIVE:
                cr.set_source_rgb(*color_hex_to_cairo(ui_theme.get_color("disable_frame").get_color()))
            else:
                cr.set_source_rgb(*color_hex_to_cairo(ui_theme.get_color("combo_entry_frame").get_color()))
            cr.rectangle(x, y, w, h)
            cr.stroke()

            if widget.state == gtk.STATE_INSENSITIVE:
                cr.set_source_rgba(*alpha_color_hex_to_cairo((ui_theme.get_color("disable_background").get_color(), 0.9)))
            else:
                cr.set_source_rgba(*alpha_color_hex_to_cairo((ui_theme.get_color("combo_entry_background").get_color(), 0.9)))
            cr.rectangle(x, y, w - 1, h - 1)
            cr.fill()

        if self.set_time == self.SET_HOUR:
            cr.set_source_rgba(*color_hex_to_cairo(self.set_time_bg_color))
            cr.rectangle(x + self.padding_x, y, self.time_width, h)
            cr.fill()

        if self.set_time == self.SET_MIN:
            cr.set_source_rgba(*color_hex_to_cairo(self.set_time_bg_color))
            cr.rectangle(x + self.padding_x + self.time_width + self.time_comma_width,
                         y,
                         self.time_width,
                         h)
            cr.fill()

        if self.set_time == self.SET_SEC:
            cr.set_source_rgba(*color_hex_to_cairo(self.set_time_bg_color))
            cr.rectangle(x + self.padding_x + (self.time_width + self.time_comma_width) * 2,
                         y,
                         self.time_width,
                         h)
            cr.fill()

        if not self.__pressed_button:
            if self.__24hour:
                self.hour_value = time.localtime().tm_hour
            else:
                self.hour_value = int(time.strftime('%I'))
            self.min_value = time.localtime().tm_min
            self.sec_value = time.localtime().tm_sec

        draw_text(cr,
                  "%02d : %02d : %02d" % (self.hour_value, self.min_value, self.sec_value),
                  x + self.padding_x,
                  y,
                  w,
                  h)

        propagate_expose(widget, event)

        return False

    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
예제 #5
0
파일: combo.py 프로젝트: masums/deepin-ui
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