def __init__(self, 
              confirm_callback=None, 
              cancel_callback=None):
     '''
     Initialize ColorSelectDialog class.
     
     @param confirm_callback: Callback when user click OK, this callback accept one argument, color string.
     @param cancel_callback: Callback when user click cancel, this callback don't accept any argument.
     '''
     DialogBox.__init__(self, _("Select color"), mask_type=DIALOG_MASK_SINGLE_PAGE)
     self.confirm_callback = confirm_callback
     self.cancel_callback = cancel_callback
     
     self.color_box = gtk.HBox()
     self.color_align = gtk.Alignment()
     self.color_align.set(0.5, 0.5, 0.0, 0.0)
     self.color_align.set_padding(10, 0, 8, 8)
     self.color_align.add(self.color_box)
     self.color_hsv = HSV()
     self.color_string = self.color_hsv.get_color_string()
     (self.color_r, self.color_g, self.color_b) = self.color_hsv.get_rgb_color()
     self.color_hsv.get_hsv_widget().connect(
         "button-release-event", 
         lambda w, e: self.update_color_info(self.color_hsv.get_color_string()))
     self.color_box.pack_start(self.color_hsv, False, False)
     
     self.color_right_box = gtk.VBox()
     self.color_right_align = gtk.Alignment()
     self.color_right_align.set(0.5, 0.5, 0.0, 0.0)
     self.color_right_align.set_padding(8, 0, 0, 0)
     self.color_right_align.add(self.color_right_box)
     self.color_box.pack_start(self.color_right_align)
     
     self.color_info_box = gtk.HBox()
     self.color_right_box.pack_start(self.color_info_box, False, False)
     
     self.color_display_box = gtk.VBox()
     self.color_display_button = gtk.Button()
     self.color_display_button.connect("expose-event", self.expose_display_button)
     self.color_display_button.set_size_request(70, 49)
     self.color_display_align = gtk.Alignment()
     self.color_display_align.set(0.5, 0.5, 1.0, 1.0)
     self.color_display_align.set_padding(5, 5, 5, 5)
     self.color_display_align.add(self.color_display_button)
     self.color_display_box.pack_start(self.color_display_align, False, False, 5)
     
     self.color_hex_box = gtk.HBox()
     self.color_hex_label = Label(_("Color value"))
     self.color_hex_box.pack_start(self.color_hex_label, False, False, 5)
     self.color_hex_entry = TextEntry(self.color_string)
     self.color_hex_entry.entry.check_text = is_hex_color
     self.color_hex_entry.entry.connect("press-return", self.press_return_color_entry)
     self.color_hex_entry.set_size(70, 24)
     self.color_hex_box.pack_start(self.color_hex_entry, False, False, 5)
     self.color_display_box.pack_start(self.color_hex_box, False, False, 5)
     
     self.color_info_box.pack_start(self.color_display_box, False, False, 5)
     
     self.color_rgb_box = gtk.VBox()
     self.color_r_box = gtk.HBox()
     self.color_r_label = Label(_("Red: "))
     self.color_r_spin = SpinBox(self.color_r, 0, 255, 1)
     self.color_r_spin.connect("value-changed", lambda s, v: self.click_rgb_spin())
     self.color_r_box.pack_start(self.color_r_label, False, False)
     self.color_r_box.pack_start(self.color_r_spin, False, False)
     self.color_g_box = gtk.HBox()
     self.color_g_label = Label(_("Green: "))
     self.color_g_spin = SpinBox(self.color_g, 0, 255, 1)
     self.color_g_spin.connect("value-changed", lambda s, v: self.click_rgb_spin())
     self.color_g_box.pack_start(self.color_g_label, False, False)
     self.color_g_box.pack_start(self.color_g_spin, False, False)
     self.color_b_box = gtk.HBox()
     self.color_b_label = Label(_("Blue: "))
     self.color_b_spin = SpinBox(self.color_b, 0, 255, 1)
     self.color_b_spin.connect("value-changed", lambda s, v: self.click_rgb_spin())
     self.color_b_box.pack_start(self.color_b_label, False, False)
     self.color_b_box.pack_start(self.color_b_spin, False, False)
     
     self.color_rgb_box.pack_start(self.color_r_box, False, False, 8)
     self.color_rgb_box.pack_start(self.color_g_box, False, False, 8)
     self.color_rgb_box.pack_start(self.color_b_box, False, False, 8)
     self.color_info_box.pack_start(self.color_rgb_box, False, False, 5)
     
     self.color_select_view = IconView()
     self.color_select_view.set_size_request(250, 60)
     self.color_select_view.connect("button-press-item", lambda view, item, x, y: self.update_color_info(item.color, False))
     self.color_select_view.draw_mask = self.get_mask_func(self.color_select_view)
     self.color_select_scrolled_window = ScrolledWindow()
     for color in self.DEFAULT_COLOR_LIST:
         self.color_select_view.add_items([ColorItem(color)])
         
     self.color_select_align = gtk.Alignment()
     self.color_select_align.set(0.5, 0.5, 1.0, 1.0)
     self.color_select_align.set_padding(10, 5, 6, 5)
     
     self.color_select_scrolled_window.add_child(self.color_select_view)
     self.color_select_scrolled_window.set_size_request(-1, 60)
     self.color_select_align.add(self.color_select_scrolled_window)
     self.color_right_box.pack_start(self.color_select_align, True, True)    
     
     self.confirm_button = Button(_("OK"))
     self.cancel_button = Button(_("Cancel"))
     
     self.confirm_button.connect("clicked", lambda w: self.click_confirm_button())
     self.cancel_button.connect("clicked", lambda w: self.click_cancel_button())
     
     self.right_button_box.set_buttons([self.confirm_button, self.cancel_button])
     self.body_box.pack_start(self.color_align, True, True)
     
     self.update_color_info(self.color_string)
class ColorSelectDialog(DialogBox):
    '''
    ColorSelectionDialog widget.
    
    @undocumented: click_confirm_button
    @undocumented: click_cancel_button
    @undocumented: click_rgb_spin
    @undocumented: press_return_color_entry
    @undocumented: expose_display_button
    '''
    
    DEFAULT_COLOR_LIST = ["#000000", "#808080", "#E20417", "#F29300", "#FFEC00", "#95BE0D", "#008F35", "#00968F", "#FFFFFF", "#C0C0C0", "#E2004E", "#E2007A", "#920A7E", "#162883", "#0069B2", "#009DE0"]
	
    def __init__(self, 
                 confirm_callback=None, 
                 cancel_callback=None):
        '''
        Initialize ColorSelectDialog class.
        
        @param confirm_callback: Callback when user click OK, this callback accept one argument, color string.
        @param cancel_callback: Callback when user click cancel, this callback don't accept any argument.
        '''
        DialogBox.__init__(self, _("Select color"), mask_type=DIALOG_MASK_SINGLE_PAGE)
        self.confirm_callback = confirm_callback
        self.cancel_callback = cancel_callback
        
        self.color_box = gtk.HBox()
        self.color_align = gtk.Alignment()
        self.color_align.set(0.5, 0.5, 0.0, 0.0)
        self.color_align.set_padding(10, 0, 8, 8)
        self.color_align.add(self.color_box)
        self.color_hsv = HSV()
        self.color_string = self.color_hsv.get_color_string()
        (self.color_r, self.color_g, self.color_b) = self.color_hsv.get_rgb_color()
        self.color_hsv.get_hsv_widget().connect(
            "button-release-event", 
            lambda w, e: self.update_color_info(self.color_hsv.get_color_string()))
        self.color_box.pack_start(self.color_hsv, False, False)
        
        self.color_right_box = gtk.VBox()
        self.color_right_align = gtk.Alignment()
        self.color_right_align.set(0.5, 0.5, 0.0, 0.0)
        self.color_right_align.set_padding(8, 0, 0, 0)
        self.color_right_align.add(self.color_right_box)
        self.color_box.pack_start(self.color_right_align)
        
        self.color_info_box = gtk.HBox()
        self.color_right_box.pack_start(self.color_info_box, False, False)
        
        self.color_display_box = gtk.VBox()
        self.color_display_button = gtk.Button()
        self.color_display_button.connect("expose-event", self.expose_display_button)
        self.color_display_button.set_size_request(70, 49)
        self.color_display_align = gtk.Alignment()
        self.color_display_align.set(0.5, 0.5, 1.0, 1.0)
        self.color_display_align.set_padding(5, 5, 5, 5)
        self.color_display_align.add(self.color_display_button)
        self.color_display_box.pack_start(self.color_display_align, False, False, 5)
        
        self.color_hex_box = gtk.HBox()
        self.color_hex_label = Label(_("Color value"))
        self.color_hex_box.pack_start(self.color_hex_label, False, False, 5)
        self.color_hex_entry = TextEntry(self.color_string)
        self.color_hex_entry.entry.check_text = is_hex_color
        self.color_hex_entry.entry.connect("press-return", self.press_return_color_entry)
        self.color_hex_entry.set_size(70, 24)
        self.color_hex_box.pack_start(self.color_hex_entry, False, False, 5)
        self.color_display_box.pack_start(self.color_hex_box, False, False, 5)
        
        self.color_info_box.pack_start(self.color_display_box, False, False, 5)
        
        self.color_rgb_box = gtk.VBox()
        self.color_r_box = gtk.HBox()
        self.color_r_label = Label(_("Red: "))
        self.color_r_spin = SpinBox(self.color_r, 0, 255, 1)
        self.color_r_spin.connect("value-changed", lambda s, v: self.click_rgb_spin())
        self.color_r_box.pack_start(self.color_r_label, False, False)
        self.color_r_box.pack_start(self.color_r_spin, False, False)
        self.color_g_box = gtk.HBox()
        self.color_g_label = Label(_("Green: "))
        self.color_g_spin = SpinBox(self.color_g, 0, 255, 1)
        self.color_g_spin.connect("value-changed", lambda s, v: self.click_rgb_spin())
        self.color_g_box.pack_start(self.color_g_label, False, False)
        self.color_g_box.pack_start(self.color_g_spin, False, False)
        self.color_b_box = gtk.HBox()
        self.color_b_label = Label(_("Blue: "))
        self.color_b_spin = SpinBox(self.color_b, 0, 255, 1)
        self.color_b_spin.connect("value-changed", lambda s, v: self.click_rgb_spin())
        self.color_b_box.pack_start(self.color_b_label, False, False)
        self.color_b_box.pack_start(self.color_b_spin, False, False)
        
        self.color_rgb_box.pack_start(self.color_r_box, False, False, 8)
        self.color_rgb_box.pack_start(self.color_g_box, False, False, 8)
        self.color_rgb_box.pack_start(self.color_b_box, False, False, 8)
        self.color_info_box.pack_start(self.color_rgb_box, False, False, 5)
        
        self.color_select_view = IconView()
        self.color_select_view.set_size_request(250, 60)
        self.color_select_view.connect("button-press-item", lambda view, item, x, y: self.update_color_info(item.color, False))
        self.color_select_view.draw_mask = self.get_mask_func(self.color_select_view)
        self.color_select_scrolled_window = ScrolledWindow()
        for color in self.DEFAULT_COLOR_LIST:
            self.color_select_view.add_items([ColorItem(color)])
            
        self.color_select_align = gtk.Alignment()
        self.color_select_align.set(0.5, 0.5, 1.0, 1.0)
        self.color_select_align.set_padding(10, 5, 6, 5)
        
        self.color_select_scrolled_window.add_child(self.color_select_view)
        self.color_select_scrolled_window.set_size_request(-1, 60)
        self.color_select_align.add(self.color_select_scrolled_window)
        self.color_right_box.pack_start(self.color_select_align, True, True)    
        
        self.confirm_button = Button(_("OK"))
        self.cancel_button = Button(_("Cancel"))
        
        self.confirm_button.connect("clicked", lambda w: self.click_confirm_button())
        self.cancel_button.connect("clicked", lambda w: self.click_cancel_button())
        
        self.right_button_box.set_buttons([self.confirm_button, self.cancel_button])
        self.body_box.pack_start(self.color_align, True, True)
        
        self.update_color_info(self.color_string)
        
    def click_confirm_button(self):
        '''
        Wrap callback when user click ok button.
        '''
        if self.confirm_callback != None:
            self.confirm_callback(self.color_hex_entry.get_text())
        
        self.destroy()
        
    def click_cancel_button(self):
        '''
        Wrap callback when user click cancel button.
        '''
        if self.cancel_callback != None:
            self.cancel_callback()
        
        self.destroy()
        
    def click_rgb_spin(self):
        '''
        Callback when user click RGB spin.
        '''
        self.update_color_info(color_rgb_to_hex((self.color_r_spin.get_value(),
                                                 self.color_g_spin.get_value(),
                                                 self.color_b_spin.get_value())))        
        
    def press_return_color_entry(self, entry):
        '''
        Callback when user press `return` key on entry.
        
        @param entry: Color input entry.
        '''
        self.update_color_info(entry.get_text())
        entry.select_all()
        
    def expose_display_button(self, widget, event):
        '''
        Callback for `expose-event` signal.
        
        @param widget: Gtk.Widget instance.
        @param event: Expose event.
        @return: Always return True        
        '''
        # Init.
        cr = widget.window.cairo_create()
        rect = widget.allocation
        
        cr.set_source_rgb(*color_hex_to_cairo(self.color_string))
        cr.rectangle(rect.x, rect.y, rect.width, rect.height)
        cr.fill()

        # Propagate expose.
        propagate_expose(widget, event)
        
        return True
        
    def update_color_info(self, color_string, clear_highlight=True):
        '''
        Update color information.

        @param color_string: Hex color string.
        @param clear_highlight: Whether clear color select view's highlight status, default is True.
        '''
        self.color_string = color_string
        (self.color_r, self.color_g, self.color_b) = color_hex_to_rgb(self.color_string)
        self.color_r_spin.update(self.color_r)
        self.color_g_spin.update(self.color_g)
        self.color_b_spin.update(self.color_b)
        self.color_hex_entry.set_text(self.color_string)
        if not color_string.startswith("#"):
            color_string = "#" + color_string
        self.color_hsv.set_current_color(gtk.gdk.color_parse(color_string))
        
        if clear_highlight:
            self.color_select_view.clear_highlight()
        
        self.color_display_button.queue_draw()