def __init__(self):
        super(IconEditArea, self).__init__()

        self.edit_area = gtk.EventBox()
        self.camera_area_vbox = gtk.VBox(False)
        self.camera_area = Webcam()
        self.camera_area_up = gtk.EventBox()
        self.camera_area_down = gtk.EventBox()
        self.camera_area_init_flag = False
        self.button_hbox = gtk.HBox(False)
        self.button_hbox_height = 40
        self.__widget_y = 92

        self.edit_area.set_size_request(self.AREA_WIDTH, self.AREA_HEIGHT)
        #self.camera_area.set_size_request(self.AREA_WIDTH, self.AREA_HEIGHT)
        self.camera_area_vbox.set_size_request(self.AREA_WIDTH, self.AREA_HEIGHT)
        self.camera_area.set_size_request(self.AREA_WIDTH, 225)
        #self.camera_area_up.set_size_request(self.AREA_WIDTH, 37)
        #self.camera_area_down.set_size_request(self.AREA_WIDTH, 37)
        self.button_hbox.set_size_request(self.AREA_WIDTH, self.button_hbox_height)

        self.button_zoom_in = ImageButton(
            app_theme.get_pixbuf("account/zoom_in.png"),
            app_theme.get_pixbuf("account/zoom_in.png"),
            app_theme.get_pixbuf("account/zoom_in.png"),
            _("zoom in"))
        self.button_zoom_out = ImageButton(
            app_theme.get_pixbuf("account/zoom_out.png"),
            app_theme.get_pixbuf("account/zoom_out.png"),
            app_theme.get_pixbuf("account/zoom_out.png"),
            _("zoom out"))
        self.button_camera = ImageButton(
            app_theme.get_pixbuf("account/camera.png"),
            app_theme.get_pixbuf("account/camera.png"),
            app_theme.get_pixbuf("account/camera.png"),
            _("Take a photo"))
        self.button_camera_again = ImageButton(
            app_theme.get_pixbuf("account/camera_again.png"),
            app_theme.get_pixbuf("account/camera_again.png"),
            app_theme.get_pixbuf("account/camera_again.png"),
            _("Try again"))

        self.button_zoom_in_align = tools.make_align(self.button_zoom_in, xalign=0.5, yalign=0.5)
        self.button_zoom_out_align = tools.make_align(self.button_zoom_out, xalign=0.5, yalign=0.5)
        self.button_camera_align = tools.make_align(self.button_camera, xalign=0.5, yalign=0.5)
        self.button_camera_again_align = tools.make_align(self.button_camera_again, xalign=0.5, yalign=0.5)

        self.button_zoom_in.connect("clicked", self.on_zoom_in_clicked_cb)
        self.button_zoom_out.connect("clicked", self.on_zoom_out_clicked_cb)
        self.button_camera.connect("clicked", self.on_camera_clicked_cb)
        self.button_camera_again.connect("clicked", self.on_camera_again_clicked_cb)

        self.box = gtk.VBox(False)
        self.box.pack_start(self.edit_area, False, False)
        #self.box.pack_start(self.button_hbox, False, False)
        #self.box.pack_start(tools.make_align(yalign=0.0, yscale=1.0))
        self.set_size(self.AREA_WIDTH, self.AREA_HEIGHT)
        self.set_size_request(self.AREA_WIDTH, self.AREA_HEIGHT)
        self.connect("expose-event", self.draw_frame_border)
        self.put(self.box, 0, 0)
        #self.put(self.button_hbox, 0, self.AREA_HEIGHT-self.button_hbox_height)

        self.edit_area.set_can_focus(True)
        self.edit_area.set_visible_window(False)
        self.edit_area.add_events(gtk.gdk.ALL_EVENTS_MASK)        
        self.edit_area.connect("button-press-event", self.__on_button_press_cb)
        self.edit_area.connect("button-release-event", self.__on_button_release_cb)
        self.edit_area.connect("motion-notify-event", self.__on_motion_notify_cb)
        #self.edit_area.connect("leave-notify-event", self.__on_leave_notify_cb)
        self.edit_area.connect("expose-event", self.__expose_edit)

        self.camera_area_down.add_events(gtk.gdk.POINTER_MOTION_MASK)
        #self.camera_area.connect("motion-notify-event", self.__on_camera_motion_notify_cb)
        self.camera_area_down.connect("motion-notify-event", self.__on_camera_motion_notify_cb)
        self.camera_area_up.connect("expose-event", self.__on_camera_expose_cb)
        self.camera_area_down.connect("expose-event", self.__on_camera_expose_cb)
        self.camera_area_vbox.pack_start(self.camera_area_up)
        self.camera_area_vbox.pack_start(self.camera_area, False, False)
        self.camera_area_vbox.pack_start(self.camera_area_down)

        #panel_size = self.button_camera.get_size_request()
        #self.panel = Panel(panel_size[0], panel_size[1], gtk.WINDOW_POPUP)
        self.panel = Panel(self.AREA_WIDTH, self.button_hbox_height, gtk.WINDOW_POPUP)
        self.panel_layout = gtk.Fixed()
        #self.panel_layout.put(self.button_camera_align, (self.AREA_WIDTH-panel_size[0])/2, 0)
        self.panel_layout.put(self.button_hbox, 0, 0)
        self.panel.add(self.panel_layout)
        self.panel.hide_panel()
        self.panel.connect("expose-event", self.__draw_panel_background)
        self.panel.connect("size-allocate", lambda w,e: w.queue_draw())

        #self.panel.connect("enter-notify-event", self.__on_camera_enter_notify_cb)
        self.panel.connect("leave-notify-event", self.__on_camera_leave_notify_cb)
        self.camera_focus_flag = True

        self.__refresh_time_id = None
        self.__button_time_id = None
        self.current_mode = self.MODE_EDIT
        self.origin_pixbuf = None
        self.origin_pixbuf_width = 0
        self.origin_pixbuf_height = 0
        self.cache_pixbuf = CachePixbuf()
        self.border_color = "#000000"

        # cursor
        self.cursor = {
            self.POS_IN_DRAG : gtk.gdk.Cursor(gtk.gdk.BOTTOM_RIGHT_CORNER),
            self.POS_IN_MOVE : gtk.gdk.Cursor(gtk.gdk.FLEUR),
            self.POS_OUT : None}
        self.cursor_current = None

        self.press_point_coord = (0, 0)
        self.position = self.POS_OUT
        self.drag_flag = False
        self.move_flag = False
        #
        self.__show_button_flag = True
        self.__button_moving_flag = False
        #self.__refresh_flag = False

        # the pixbuf shown area
        self.pixbuf_offset_x = 0
        self.pixbuf_offset_y = 0
        self.pixbuf_offset_cmp_x = 0
        self.pixbuf_offset_cmp_y = 0
        self.pixbuf_x = 0
        self.pixbuf_y = 0
        self.pixbuf_w = self.AREA_WIDTH
        self.pixbuf_h = self.AREA_HEIGHT
        # the select box area
        self.edit_coord_x = 0
        self.edit_coord_y = 0
        self.edit_coord_w = self.AREA_WIDTH
        self.edit_coord_h = self.AREA_HEIGHT
        self.edit_coord_backup_x = 0
        self.edit_coord_backup_y = 0
        self.edit_coord_backup_w = self.AREA_WIDTH
        self.edit_coord_backup_h = self.AREA_HEIGHT

        self.drag_point_x = 0
        self.drag_point_y = 0
        self.__update_drag_point_coord()
class IconEditArea(gtk.Layout):
    __gsignals__ = {
        "pixbuf-changed": (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))}

    AREA_WIDTH = 300
    AREA_HEIGHT = 300
    DRAG_WIDTH = 10
    MIN_SIZE = 150

    POS_OUT = 0
    POS_IN_MOVE = 1
    POS_IN_DRAG = 2

    MODE_CAMERA = 0
    MODE_CAMERA_EDIT = 1
    MODE_EDIT = 2

    def __init__(self):
        super(IconEditArea, self).__init__()

        self.edit_area = gtk.EventBox()
        self.camera_area_vbox = gtk.VBox(False)
        self.camera_area = Webcam()
        self.camera_area_up = gtk.EventBox()
        self.camera_area_down = gtk.EventBox()
        self.camera_area_init_flag = False
        self.button_hbox = gtk.HBox(False)
        self.button_hbox_height = 40
        self.__widget_y = 92

        self.edit_area.set_size_request(self.AREA_WIDTH, self.AREA_HEIGHT)
        #self.camera_area.set_size_request(self.AREA_WIDTH, self.AREA_HEIGHT)
        self.camera_area_vbox.set_size_request(self.AREA_WIDTH, self.AREA_HEIGHT)
        self.camera_area.set_size_request(self.AREA_WIDTH, 225)
        #self.camera_area_up.set_size_request(self.AREA_WIDTH, 37)
        #self.camera_area_down.set_size_request(self.AREA_WIDTH, 37)
        self.button_hbox.set_size_request(self.AREA_WIDTH, self.button_hbox_height)

        self.button_zoom_in = ImageButton(
            app_theme.get_pixbuf("account/zoom_in.png"),
            app_theme.get_pixbuf("account/zoom_in.png"),
            app_theme.get_pixbuf("account/zoom_in.png"),
            _("zoom in"))
        self.button_zoom_out = ImageButton(
            app_theme.get_pixbuf("account/zoom_out.png"),
            app_theme.get_pixbuf("account/zoom_out.png"),
            app_theme.get_pixbuf("account/zoom_out.png"),
            _("zoom out"))
        self.button_camera = ImageButton(
            app_theme.get_pixbuf("account/camera.png"),
            app_theme.get_pixbuf("account/camera.png"),
            app_theme.get_pixbuf("account/camera.png"),
            _("Take a photo"))
        self.button_camera_again = ImageButton(
            app_theme.get_pixbuf("account/camera_again.png"),
            app_theme.get_pixbuf("account/camera_again.png"),
            app_theme.get_pixbuf("account/camera_again.png"),
            _("Try again"))

        self.button_zoom_in_align = tools.make_align(self.button_zoom_in, xalign=0.5, yalign=0.5)
        self.button_zoom_out_align = tools.make_align(self.button_zoom_out, xalign=0.5, yalign=0.5)
        self.button_camera_align = tools.make_align(self.button_camera, xalign=0.5, yalign=0.5)
        self.button_camera_again_align = tools.make_align(self.button_camera_again, xalign=0.5, yalign=0.5)

        self.button_zoom_in.connect("clicked", self.on_zoom_in_clicked_cb)
        self.button_zoom_out.connect("clicked", self.on_zoom_out_clicked_cb)
        self.button_camera.connect("clicked", self.on_camera_clicked_cb)
        self.button_camera_again.connect("clicked", self.on_camera_again_clicked_cb)

        self.box = gtk.VBox(False)
        self.box.pack_start(self.edit_area, False, False)
        #self.box.pack_start(self.button_hbox, False, False)
        #self.box.pack_start(tools.make_align(yalign=0.0, yscale=1.0))
        self.set_size(self.AREA_WIDTH, self.AREA_HEIGHT)
        self.set_size_request(self.AREA_WIDTH, self.AREA_HEIGHT)
        self.connect("expose-event", self.draw_frame_border)
        self.put(self.box, 0, 0)
        #self.put(self.button_hbox, 0, self.AREA_HEIGHT-self.button_hbox_height)

        self.edit_area.set_can_focus(True)
        self.edit_area.set_visible_window(False)
        self.edit_area.add_events(gtk.gdk.ALL_EVENTS_MASK)        
        self.edit_area.connect("button-press-event", self.__on_button_press_cb)
        self.edit_area.connect("button-release-event", self.__on_button_release_cb)
        self.edit_area.connect("motion-notify-event", self.__on_motion_notify_cb)
        #self.edit_area.connect("leave-notify-event", self.__on_leave_notify_cb)
        self.edit_area.connect("expose-event", self.__expose_edit)

        self.camera_area_down.add_events(gtk.gdk.POINTER_MOTION_MASK)
        #self.camera_area.connect("motion-notify-event", self.__on_camera_motion_notify_cb)
        self.camera_area_down.connect("motion-notify-event", self.__on_camera_motion_notify_cb)
        self.camera_area_up.connect("expose-event", self.__on_camera_expose_cb)
        self.camera_area_down.connect("expose-event", self.__on_camera_expose_cb)
        self.camera_area_vbox.pack_start(self.camera_area_up)
        self.camera_area_vbox.pack_start(self.camera_area, False, False)
        self.camera_area_vbox.pack_start(self.camera_area_down)

        #panel_size = self.button_camera.get_size_request()
        #self.panel = Panel(panel_size[0], panel_size[1], gtk.WINDOW_POPUP)
        self.panel = Panel(self.AREA_WIDTH, self.button_hbox_height, gtk.WINDOW_POPUP)
        self.panel_layout = gtk.Fixed()
        #self.panel_layout.put(self.button_camera_align, (self.AREA_WIDTH-panel_size[0])/2, 0)
        self.panel_layout.put(self.button_hbox, 0, 0)
        self.panel.add(self.panel_layout)
        self.panel.hide_panel()
        self.panel.connect("expose-event", self.__draw_panel_background)
        self.panel.connect("size-allocate", lambda w,e: w.queue_draw())

        #self.panel.connect("enter-notify-event", self.__on_camera_enter_notify_cb)
        self.panel.connect("leave-notify-event", self.__on_camera_leave_notify_cb)
        self.camera_focus_flag = True

        self.__refresh_time_id = None
        self.__button_time_id = None
        self.current_mode = self.MODE_EDIT
        self.origin_pixbuf = None
        self.origin_pixbuf_width = 0
        self.origin_pixbuf_height = 0
        self.cache_pixbuf = CachePixbuf()
        self.border_color = "#000000"

        # cursor
        self.cursor = {
            self.POS_IN_DRAG : gtk.gdk.Cursor(gtk.gdk.BOTTOM_RIGHT_CORNER),
            self.POS_IN_MOVE : gtk.gdk.Cursor(gtk.gdk.FLEUR),
            self.POS_OUT : None}
        self.cursor_current = None

        self.press_point_coord = (0, 0)
        self.position = self.POS_OUT
        self.drag_flag = False
        self.move_flag = False
        #
        self.__show_button_flag = True
        self.__button_moving_flag = False
        #self.__refresh_flag = False

        # the pixbuf shown area
        self.pixbuf_offset_x = 0
        self.pixbuf_offset_y = 0
        self.pixbuf_offset_cmp_x = 0
        self.pixbuf_offset_cmp_y = 0
        self.pixbuf_x = 0
        self.pixbuf_y = 0
        self.pixbuf_w = self.AREA_WIDTH
        self.pixbuf_h = self.AREA_HEIGHT
        # the select box area
        self.edit_coord_x = 0
        self.edit_coord_y = 0
        self.edit_coord_w = self.AREA_WIDTH
        self.edit_coord_h = self.AREA_HEIGHT
        self.edit_coord_backup_x = 0
        self.edit_coord_backup_y = 0
        self.edit_coord_backup_w = self.AREA_WIDTH
        self.edit_coord_backup_h = self.AREA_HEIGHT

        self.drag_point_x = 0
        self.drag_point_y = 0
        self.__update_drag_point_coord()

    def draw_frame_border(self, widget, event):
        cr = widget.window.cairo_create()
        with cairo_disable_antialias(cr):
            cr.set_line_width(1)
            x, y, w, h = widget.allocation
            cr.set_source_rgb(*color_hex_to_cairo(TREEVIEW_BORDER_COLOR))
            cr.rectangle(x-1, y-1, w+2, h+2)
            cr.stroke()

    def on_camera_again_clicked_cb(self, button):
        self.set_camera_mode()

    def on_camera_clicked_cb(self, button):
        self.current_mode = self.MODE_CAMERA_EDIT
        drawable = self.camera_area.window
        colormap = drawable.get_colormap()
        pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 0, 8, *drawable.get_size())
        pixbuf = pixbuf.get_from_drawable(drawable, colormap, 0, 0, 0, 0, *drawable.get_size()) 
        self.__edit_picture(pixbuf)
        container_remove_all(self.button_hbox)
        self.button_hbox.pack_start(self.button_zoom_in_align)
        self.button_hbox.pack_start(self.button_zoom_out_align)
        self.button_hbox.pack_start(self.button_camera_again_align)
        self.button_hbox.show_all()

    def on_zoom_in_clicked_cb(self, button):
        if self.pixbuf_w >= self.origin_pixbuf_width or self.pixbuf_h >= self.origin_pixbuf_height:
            print "has max size"
            button.set_sensitive(False)
            return
        width = int(self.pixbuf_w * 1.1)
        height = int(self.pixbuf_h * 1.1)
        if width >= self.origin_pixbuf_width:
            width = self.origin_pixbuf_width
        if height >= self.origin_pixbuf_height:
            height = self.origin_pixbuf_height
        self.cache_pixbuf.scale(self.origin_pixbuf, width, height)
        # count show area
        self.pixbuf_w = width
        self.pixbuf_h = height
        self.pixbuf_x = (self.AREA_WIDTH - width) / 2
        self.pixbuf_y = (self.AREA_HEIGHT - height) / 2
        if self.pixbuf_x < 0:
            self.pixbuf_offset_x -= self.pixbuf_x
            if self.pixbuf_offset_x + self.AREA_WIDTH > self.pixbuf_w:
                self.pixbuf_offset_x = self.pixbuf_w - self.AREA_WIDTH
            self.pixbuf_x = 0
        if self.pixbuf_y < 0:
            self.pixbuf_offset_y -= self.pixbuf_y
            if self.pixbuf_offset_y + self.AREA_HEIGHT > self.pixbuf_h:
                self.pixbuf_offset_y = self.pixbuf_h - self.AREA_HEIGHT
            self.pixbuf_y = 0
        self.__update_drag_point_coord()
        self.emit_changed()
        if self.pixbuf_w >= self.origin_pixbuf_width or self.pixbuf_h >= self.origin_pixbuf_height:
            button.set_sensitive(False)
        if not (self.pixbuf_w <= self.edit_coord_w or self.pixbuf_h <= self.edit_coord_h) \
                and not self.button_zoom_out.get_sensitive():
            self.button_zoom_out.set_sensitive(True)

    def on_zoom_out_clicked_cb(self, button):
        if self.edit_coord_w < self.MIN_SIZE or self.edit_coord_h < self.MIN_SIZE:
            self.edit_coord_w = self.edit_coord_h = self.MIN_SIZE
        if self.pixbuf_w <= self.edit_coord_w or self.pixbuf_h <= self.edit_coord_h:
            print "has min size"
            button.set_sensitive(False)
            return
        width = int(self.pixbuf_w * 0.9)
        height = int(self.pixbuf_h * 0.9)
        if height >= width and width <= self.edit_coord_w:
            height = int(float(height) / width * self.edit_coord_w)
            width = int(self.edit_coord_w)
        elif height < self.edit_coord_h:
            width = int(float(width) / height * self.edit_coord_h)
            height = int(self.edit_coord_h)
        self.cache_pixbuf.scale(self.origin_pixbuf, width, height)
        # count show area
        self.pixbuf_w = width
        self.pixbuf_h = height
        self.pixbuf_x = (self.AREA_WIDTH - width) / 2
        self.pixbuf_y = (self.AREA_HEIGHT - height) / 2
        # count pixbuf offset
        if self.pixbuf_x < 0:
            self.pixbuf_offset_x -= self.pixbuf_x
            if self.pixbuf_offset_x + self.AREA_WIDTH > self.pixbuf_w:
                self.pixbuf_offset_x = self.pixbuf_w - self.AREA_WIDTH
            self.pixbuf_x = 0
        if self.pixbuf_y < 0:
            self.pixbuf_offset_y -= self.pixbuf_y
            if self.pixbuf_offset_y + self.AREA_HEIGHT > self.pixbuf_h:
                self.pixbuf_offset_y = self.pixbuf_h - self.AREA_HEIGHT
            self.pixbuf_y = 0
        if self.pixbuf_x + self.pixbuf_w < self.AREA_WIDTH:
            self.pixbuf_offset_x = 0
        if self.pixbuf_y + self.pixbuf_h < self.AREA_HEIGHT:
            self.pixbuf_offset_y = 0
        # count edit area
        if self.edit_coord_x < self.pixbuf_x:
            self.edit_coord_x = self.pixbuf_x
        if self.edit_coord_y < self.pixbuf_y:
            self.edit_coord_y = self.pixbuf_y
        right_pos = min(self.pixbuf_x+self.pixbuf_w, self.AREA_WIDTH)
        bottom_pos = min(self.pixbuf_y+self.pixbuf_h, self.AREA_HEIGHT)
        if self.edit_coord_x + self.edit_coord_w > right_pos:
            self.edit_coord_x = right_pos - self.edit_coord_w
        if self.edit_coord_y + self.edit_coord_h > bottom_pos:
            self.edit_coord_y = bottom_pos - self.edit_coord_h
        self.__update_drag_point_coord()
        self.emit_changed()
        if self.pixbuf_w <= self.edit_coord_w or self.pixbuf_h <= self.edit_coord_h:
            button.set_sensitive(False)
        if not (self.pixbuf_w >= self.origin_pixbuf_width or self.pixbuf_h >= self.origin_pixbuf_height) \
                and not self.button_zoom_in.get_sensitive():
            self.button_zoom_in.set_sensitive(True)

    def __expose_edit(self, widget, event):
        pixbuf = self.cache_pixbuf.get_cache()
        if not pixbuf:
            return
        cr = widget.window.cairo_create()
        cr.set_source_pixbuf(pixbuf, self.pixbuf_x-self.pixbuf_offset_x, self.pixbuf_y-self.pixbuf_offset_y)
        cr.paint()
        self.__draw_mask(cr, widget.allocation)
        self.__draw_frame(cr, widget.allocation)
        return True

    def __draw_frame(self, cr, allocation):
        with cairo_disable_antialias(cr):
            cr.set_line_width(1)
            cr.save()
            cr.set_dash((9, 3))
            cr.set_source_rgb(*color_hex_to_cairo(self.border_color))
            x = self.edit_coord_x
            y = self.edit_coord_y
            w = self.edit_coord_w
            h = self.edit_coord_h
            if x == 0:
                x = 1
            if y == 0:
                y = 1
            if x + w > self.AREA_WIDTH:
                w = self.AREA_WIDTH- x
            if y + h > self.AREA_HEIGHT:
                h = self.AREA_HEIGHT- y
            cr.rectangle(x, y, w, h)
            cr.stroke()

            cr.set_dash((3, 9))
            cr.set_source_rgb(1, 1, 1)
            cr.rectangle(x, y, w, h)
            cr.stroke()
            cr.restore()

            cr.set_source_rgb(*color_hex_to_cairo(self.border_color))
            cr.rectangle(self.drag_point_x, self.drag_point_y, self.DRAG_WIDTH, self.DRAG_WIDTH)
            cr.stroke()

    def __draw_mask(self, cr, allocation):
        x, y, w, h = allocation
        x = 0
        y = 0
        # Draw left.
        if self.edit_coord_x > 0:
            cr.set_source_rgba(0, 0, 0, 0.5)
            cr.rectangle(x, y, self.edit_coord_x, h)
            cr.fill()

        # Draw top.
        if self.edit_coord_y > 0:
            cr.set_source_rgba(0, 0, 0, 0.5)
            cr.rectangle(x+self.edit_coord_x, y, w-self.edit_coord_x, self.edit_coord_y)
            cr.fill()

        # Draw bottom.
        if self.edit_coord_y + self.edit_coord_h < h:
            cr.set_source_rgba(0, 0, 0, 0.5)
            cr.rectangle(x+self.edit_coord_x, y+self.edit_coord_y+self.edit_coord_h,
                         w-self.edit_coord_x, h-self.edit_coord_y-self.edit_coord_h)
            cr.fill()

        # Draw right.
        if self.edit_coord_x + self.edit_coord_w < w:
            cr.set_source_rgba(0, 0, 0, 0.5)
            cr.rectangle(x+self.edit_coord_x+self.edit_coord_w, y+self.edit_coord_y,
                         w-self.edit_coord_x-self.edit_coord_w, self.edit_coord_h)
            cr.fill()

    def set_pixbuf(self, pixbuf):
        if not pixbuf:
            self.cache_pixbuf.cache_pixbuf = None
            self.edit_area.queue_draw()
            self.emit_changed()
            self.button_zoom_in.set_sensitive(False)
            self.button_zoom_out.set_sensitive(False)
            return
        self.origin_pixbuf = pixbuf
        self.origin_pixbuf_width = w = pixbuf.get_width()
        self.origin_pixbuf_height = h = pixbuf.get_height()
        if h >= w:
            w = int(float(w) / h * self.AREA_HEIGHT)
            h = self.AREA_HEIGHT
            if w < self.MIN_SIZE:
                h = int(float(h) / w * self.MIN_SIZE)
                w = self.MIN_SIZE
            self.edit_coord_w = self.edit_coord_h = w
        else:
            h = int(float(h) / w * self.AREA_WIDTH)
            w = self.AREA_WIDTH
            if h < self.MIN_SIZE:
                w = int(float(w) / h * self.MIN_SIZE)
                h = self.MIN_SIZE
            self.edit_coord_w = self.edit_coord_h = h
        # count the offset coord
        self.pixbuf_offset_x = 0
        self.pixbuf_offset_y = 0
        self.pixbuf_x = 0
        self.pixbuf_y = 0
        self.pixbuf_w = w
        self.pixbuf_h = h
        if w < self.AREA_WIDTH:
            self.pixbuf_x = (self.AREA_WIDTH - w) / 2
        if h < self.AREA_HEIGHT :
            self.pixbuf_y = (self.AREA_HEIGHT - h) / 2
        # update select box coord
        self.edit_coord_x = self.pixbuf_x
        self.edit_coord_y = self.pixbuf_y
        self.cache_pixbuf.scale(pixbuf, w, h)
        ######
        self.edit_coord_w = self.edit_coord_h = self.MIN_SIZE
        self.edit_coord_x = self.edit_coord_y = (self.AREA_WIDTH - self.MIN_SIZE) / 2
        ######
        self.drag_point_x = self.edit_coord_x + self.edit_coord_w - self.DRAG_WIDTH
        self.drag_point_y = self.edit_coord_y + self.edit_coord_h - self.DRAG_WIDTH
        self.edit_area.queue_draw()
        self.emit_changed()
        self.__update_button_sensitive()

    def emit_changed(self):
        pix = self.cache_pixbuf.get_cache()
        if pix:
            pix = pix.subpixbuf(int(self.edit_coord_x-self.pixbuf_x+self.pixbuf_offset_x),
                                int(self.edit_coord_y-self.pixbuf_y+self.pixbuf_offset_y),
                                int(self.edit_coord_w),
                                int(self.edit_coord_h))
        self.emit("pixbuf-changed", pix)

    def get_pixbuf(self):
        return self.cache_pixbuf.get_cache()

    def set_cursor(self):
        if not self.edit_area.window:
            return
        if self.cursor_current != self.cursor[self.position]:
            self.cursor_current = self.cursor[self.position]
            self.edit_area.window.set_cursor(self.cursor_current)

    def __on_button_press_cb(self, widget, event):
        self.__update_position(event.x, event.y)
        if self.position == self.POS_IN_DRAG:
            self.drag_flag = True
        elif self.position == self.POS_IN_MOVE:
            self.move_flag = True
        self.press_point_coord = (event.x, event.y)
        self.edit_coord_backup_x = self.edit_coord_x
        self.edit_coord_backup_y = self.edit_coord_y
        self.edit_coord_backup_w = self.edit_coord_w
        self.edit_coord_backup_h = self.edit_coord_h

    def __on_button_release_cb(self, widget, event):
        self.drag_flag = False
        self.move_flag = False

    def __on_motion_notify_cb(self, widget, event):
        # if application window has not grab focus, return function
        if not self.camera_focus_flag:
            return
        x, y, w, h = widget.allocation
        if not self.drag_flag and not self.move_flag and \
                not self.panel.get_visible() and \
                y+self.AREA_HEIGHT-self.button_hbox_height<event.y<y+self.AREA_HEIGHT:
            self.slide_button_show(event)
            return
        pixbuf = self.cache_pixbuf.get_cache()
        if not pixbuf:
            return
        if not self.drag_flag and not self.move_flag:
            self.__update_position(event.x, event.y)
            self.set_cursor()
        right_pos = min(self.pixbuf_x+self.pixbuf_w, self.AREA_WIDTH)
        bottom_pos = min(self.pixbuf_y+self.pixbuf_h, self.AREA_HEIGHT)
        if self.move_flag:
            self.edit_coord_x = self.edit_coord_backup_x + event.x - self.press_point_coord[0]
            self.edit_coord_y = self.edit_coord_backup_y + event.y - self.press_point_coord[1]

            # check left
            if self.edit_coord_x < self.pixbuf_x:
                # move the pixbuf into canvas
                if self.pixbuf_w > self.AREA_WIDTH:
                    if self.pixbuf_offset_x > 0:
                        self.pixbuf_offset_x -= self.pixbuf_x - self.edit_coord_x
                    if self.pixbuf_offset_x < 0:
                        self.pixbuf_offset_x = 0
                self.edit_coord_x = self.pixbuf_x
            # check top
            if self.edit_coord_y < self.pixbuf_y:
                # move the pixbuf into canvas
                if self.pixbuf_h > self.AREA_HEIGHT:
                    if self.pixbuf_offset_y > 0:
                        self.pixbuf_offset_y -= self.pixbuf_y - self.edit_coord_y
                    if self.pixbuf_offset_y < 0:
                        self.pixbuf_offset_y = 0
                self.edit_coord_y = self.pixbuf_y
            # check right
            if self.edit_coord_x + self.edit_coord_w > right_pos:
                # move the pixbuf into canvas
                if self.pixbuf_w > self.AREA_WIDTH:
                    if self.pixbuf_offset_x + self.AREA_WIDTH < self.pixbuf_w:
                        self.pixbuf_offset_x += (self.edit_coord_x + self.edit_coord_w) - self.AREA_WIDTH
                    if self.pixbuf_offset_x + self.AREA_WIDTH > self.pixbuf_w:
                        self.pixbuf_offset_x = self.pixbuf_w - self.AREA_WIDTH
                self.edit_coord_x = right_pos - self.edit_coord_w
            # check bottom
            if self.edit_coord_y + self.edit_coord_h > bottom_pos:
                # move the pixbuf into canvas
                if self.pixbuf_h > self.AREA_HEIGHT:
                    if self.pixbuf_offset_y + self.AREA_HEIGHT < self.pixbuf_h:
                        self.pixbuf_offset_y += (self.edit_coord_y + self.edit_coord_h) - self.AREA_HEIGHT
                    if self.pixbuf_offset_y + self.AREA_HEIGHT > self.pixbuf_h:
                        self.pixbuf_offset_y = self.pixbuf_h - self.AREA_HEIGHT
                self.edit_coord_y = bottom_pos - self.edit_coord_h
        elif self.drag_flag:
            drag_offset = max(event.x - self.press_point_coord[0],
                              event.y - self.press_point_coord[1])
            self.edit_coord_h = self.edit_coord_w = self.edit_coord_backup_w + drag_offset
            if self.edit_coord_h < self.MIN_SIZE or self.edit_coord_w < self.MIN_SIZE:
                self.edit_coord_h = self.edit_coord_w = self.MIN_SIZE

            if self.edit_coord_x + self.edit_coord_w > right_pos:
                self.edit_coord_h = self.edit_coord_w = right_pos - self.edit_coord_x
            if self.edit_coord_y + self.edit_coord_h > bottom_pos:
                self.edit_coord_h = self.edit_coord_w = bottom_pos - self.edit_coord_y
            # check zoom_out button sensitive
            # if edit_area's size more than pixbuf size, then disable zoom_out button
            # else enable zoom_out button
            if not (self.pixbuf_w <= self.edit_coord_w or self.pixbuf_h <= self.edit_coord_h):
                if not self.button_zoom_out.get_sensitive():
                    self.button_zoom_out.set_sensitive(True)
            else:
                if self.button_zoom_out.get_sensitive():
                    self.button_zoom_out.set_sensitive(False)
        self.__update_drag_point_coord()

    def __on_camera_motion_notify_cb(self, widget, event):
        if not self.camera_focus_flag:
            return
        x, y, w, h = widget.allocation
        #if not self.panel.get_visible() and \
                #y+self.AREA_HEIGHT-self.button_hbox_height<event.y<y+self.AREA_HEIGHT:
        if not self.panel.get_visible():
            if self.__refresh_time_id:
                gtk.timeout_remove(self.__refresh_time_id)
            if self.__button_time_id:
                gtk.timeout_remove(self.__button_time_id)
            self.__button_time_id = gobject.timeout_add(30, self.__slide_camera_button_show)
            #self.panel_layout.move(self.button_hbox, 0, self.button_hbox_height)
            x = event.x_root - event.x
            y = event.y_root - event.y - widget.allocation.y + self.AREA_HEIGHT - self.button_hbox_height
            self.set_win_pos(event.x_root - event.x - self.allocation.x,
                             event.y_root - event.y - widget.allocation.y - self.allocation.y)
            self.panel.move(int(x), int(y) + self.button_hbox_height)
            self.panel.show_panel()

    def __draw_panel_background(self, widget, event):
        cr = widget.window.cairo_create()
        x, y, w, h = widget.allocation
        cr.set_source_rgb(0, 0, 0)
        cr.set_operator(OPERATOR_SOURCE)
        cr.paint()

        cr.set_source_rgba(0, 0, 0, 0.5)
        cr.rectangle(x, y, w, h)
        cr.paint()
        propagate_expose(widget, event)
        return True

    def __on_camera_expose_cb(self, widget, event):
        cr = widget.window.cairo_create()
        cr.set_source_rgb(0, 0, 0)
        cr.rectangle(0, 0, widget.allocation.width, widget.allocation.height)
        cr.fill()
        return True

    def __on_camera_enter_notify_cb(self, widget, event):
        pass

    def __on_camera_leave_notify_cb(self, widget, event):
        x, y, w, h = widget.allocation
        if (event.y_root == event.x_root == 0.0) or (x < event.x < x+w and y < event.y < y+h):
            return
        if self.__button_time_id:
            gtk.timeout_remove(self.__button_time_id)
        self.__button_time_id = gobject.timeout_add(30, self.__slide_camera_button_hide)

    def __update_drag_point_coord(self):
        new_x = self.edit_coord_x + self.edit_coord_w - self.DRAG_WIDTH
        new_y = self.edit_coord_y + self.edit_coord_h - self.DRAG_WIDTH
        if self.drag_point_x != new_x or self.drag_point_y != new_y or\
                self.pixbuf_offset_cmp_x != self.pixbuf_offset_x or\
                self.pixbuf_offset_cmp_y != self.pixbuf_offset_y:
            self.drag_point_x = new_x
            self.drag_point_y = new_y
            self.pixbuf_offset_cmp_x = self.pixbuf_offset_x
            self.pixbuf_offset_cmp_y = self.pixbuf_offset_y
            self.emit_changed()
        self.edit_area.queue_draw()

    def __update_position(self, x, y):
        if self.drag_point_x <= x <= self.drag_point_x + self.DRAG_WIDTH and\
                self.drag_point_y <= y <= self.drag_point_y + self.DRAG_WIDTH:
            self.position = self.POS_IN_DRAG
        elif self.edit_coord_x <= x <= self.edit_coord_x + self.edit_coord_w and\
                self.edit_coord_y <= y <= self.edit_coord_y + self.edit_coord_h:
            self.position = self.POS_IN_MOVE
        else:
            self.position = self.POS_OUT

    def set_camera_mode(self):
        self.current_mode = self.MODE_CAMERA
        self.__camera_picture()
        self.__refresh_camera_button()

    def __camera_picture(self):
        self.set_pixbuf(None)
        if self.edit_area in self.box.get_children():
            self.box.remove(self.edit_area)
        if not self.camera_area_vbox in self.box.get_children():
            self.box.pack_start(self.camera_area_vbox, False, False)
            self.box.reorder_child(self.camera_area_vbox, 0)
        container_remove_all(self.button_hbox)
        self.button_hbox.pack_start(self.button_camera_align)
        self.button_hbox.show_all()
        self.show_all()
        try:
            if not self.camera_area.video_player:
                self.camera_area.create_video_pipeline()
            else:
                self.camera_start()
        except Exception, e:
            print e
예제 #3
0
class IconEditArea(gtk.Layout):
    __gsignals__ = {
        "pixbuf-changed":
        (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, ))
    }

    AREA_WIDTH = 300
    AREA_HEIGHT = 300
    DRAG_WIDTH = 10
    MIN_SIZE = 150

    POS_OUT = 0
    POS_IN_MOVE = 1
    POS_IN_DRAG = 2

    MODE_CAMERA = 0
    MODE_CAMERA_EDIT = 1
    MODE_EDIT = 2

    def __init__(self):
        super(IconEditArea, self).__init__()

        self.edit_area = gtk.EventBox()
        self.camera_area_vbox = gtk.VBox(False)
        self.camera_area = Webcam()
        self.camera_area_up = gtk.EventBox()
        self.camera_area_down = gtk.EventBox()
        self.camera_area_init_flag = False
        self.button_hbox = gtk.HBox(False)
        self.button_hbox_height = 40
        self.__widget_y = 92

        self.edit_area.set_size_request(self.AREA_WIDTH, self.AREA_HEIGHT)
        #self.camera_area.set_size_request(self.AREA_WIDTH, self.AREA_HEIGHT)
        self.camera_area_vbox.set_size_request(self.AREA_WIDTH,
                                               self.AREA_HEIGHT)
        self.camera_area.set_size_request(self.AREA_WIDTH, 225)
        #self.camera_area_up.set_size_request(self.AREA_WIDTH, 37)
        #self.camera_area_down.set_size_request(self.AREA_WIDTH, 37)
        self.button_hbox.set_size_request(self.AREA_WIDTH,
                                          self.button_hbox_height)

        self.button_zoom_in = ImageButton(
            app_theme.get_pixbuf("account/zoom_in.png"),
            app_theme.get_pixbuf("account/zoom_in.png"),
            app_theme.get_pixbuf("account/zoom_in.png"), _("zoom in"))
        self.button_zoom_out = ImageButton(
            app_theme.get_pixbuf("account/zoom_out.png"),
            app_theme.get_pixbuf("account/zoom_out.png"),
            app_theme.get_pixbuf("account/zoom_out.png"), _("zoom out"))
        self.button_camera = ImageButton(
            app_theme.get_pixbuf("account/camera.png"),
            app_theme.get_pixbuf("account/camera.png"),
            app_theme.get_pixbuf("account/camera.png"), _("Take a photo"))
        self.button_camera_again = ImageButton(
            app_theme.get_pixbuf("account/camera_again.png"),
            app_theme.get_pixbuf("account/camera_again.png"),
            app_theme.get_pixbuf("account/camera_again.png"), _("Try again"))

        self.button_zoom_in_align = tools.make_align(self.button_zoom_in,
                                                     xalign=0.5,
                                                     yalign=0.5)
        self.button_zoom_out_align = tools.make_align(self.button_zoom_out,
                                                      xalign=0.5,
                                                      yalign=0.5)
        self.button_camera_align = tools.make_align(self.button_camera,
                                                    xalign=0.5,
                                                    yalign=0.5)
        self.button_camera_again_align = tools.make_align(
            self.button_camera_again, xalign=0.5, yalign=0.5)

        self.button_zoom_in.connect("clicked", self.on_zoom_in_clicked_cb)
        self.button_zoom_out.connect("clicked", self.on_zoom_out_clicked_cb)
        self.button_camera.connect("clicked", self.on_camera_clicked_cb)
        self.button_camera_again.connect("clicked",
                                         self.on_camera_again_clicked_cb)

        self.box = gtk.VBox(False)
        self.box.pack_start(self.edit_area, False, False)
        #self.box.pack_start(self.button_hbox, False, False)
        #self.box.pack_start(tools.make_align(yalign=0.0, yscale=1.0))
        self.set_size(self.AREA_WIDTH, self.AREA_HEIGHT)
        self.set_size_request(self.AREA_WIDTH, self.AREA_HEIGHT)
        self.connect("expose-event", self.draw_frame_border)
        self.put(self.box, 0, 0)
        #self.put(self.button_hbox, 0, self.AREA_HEIGHT-self.button_hbox_height)

        self.edit_area.set_can_focus(True)
        self.edit_area.set_visible_window(False)
        self.edit_area.add_events(gtk.gdk.ALL_EVENTS_MASK)
        self.edit_area.connect("button-press-event", self.__on_button_press_cb)
        self.edit_area.connect("button-release-event",
                               self.__on_button_release_cb)
        self.edit_area.connect("motion-notify-event",
                               self.__on_motion_notify_cb)
        #self.edit_area.connect("leave-notify-event", self.__on_leave_notify_cb)
        self.edit_area.connect("expose-event", self.__expose_edit)

        self.camera_area_down.add_events(gtk.gdk.POINTER_MOTION_MASK)
        #self.camera_area.connect("motion-notify-event", self.__on_camera_motion_notify_cb)
        self.camera_area_down.connect("motion-notify-event",
                                      self.__on_camera_motion_notify_cb)
        self.camera_area_up.connect("expose-event", self.__on_camera_expose_cb)
        self.camera_area_down.connect("expose-event",
                                      self.__on_camera_expose_cb)
        self.camera_area_vbox.pack_start(self.camera_area_up)
        self.camera_area_vbox.pack_start(self.camera_area, False, False)
        self.camera_area_vbox.pack_start(self.camera_area_down)

        #panel_size = self.button_camera.get_size_request()
        #self.panel = Panel(panel_size[0], panel_size[1], gtk.WINDOW_POPUP)
        self.panel = Panel(self.AREA_WIDTH, self.button_hbox_height,
                           gtk.WINDOW_POPUP)
        self.panel_layout = gtk.Fixed()
        #self.panel_layout.put(self.button_camera_align, (self.AREA_WIDTH-panel_size[0])/2, 0)
        self.panel_layout.put(self.button_hbox, 0, 0)
        self.panel.add(self.panel_layout)
        self.panel.hide_panel()
        self.panel.connect("expose-event", self.__draw_panel_background)
        self.panel.connect("size-allocate", lambda w, e: w.queue_draw())

        #self.panel.connect("enter-notify-event", self.__on_camera_enter_notify_cb)
        self.panel.connect("leave-notify-event",
                           self.__on_camera_leave_notify_cb)
        self.camera_focus_flag = True

        self.__refresh_time_id = None
        self.__button_time_id = None
        self.current_mode = self.MODE_EDIT
        self.origin_pixbuf = None
        self.origin_pixbuf_width = 0
        self.origin_pixbuf_height = 0
        self.cache_pixbuf = CachePixbuf()
        self.border_color = "#000000"

        # cursor
        self.cursor = {
            self.POS_IN_DRAG: gtk.gdk.Cursor(gtk.gdk.BOTTOM_RIGHT_CORNER),
            self.POS_IN_MOVE: gtk.gdk.Cursor(gtk.gdk.FLEUR),
            self.POS_OUT: None
        }
        self.cursor_current = None

        self.press_point_coord = (0, 0)
        self.position = self.POS_OUT
        self.drag_flag = False
        self.move_flag = False
        #
        self.__show_button_flag = True
        self.__button_moving_flag = False
        #self.__refresh_flag = False

        # the pixbuf shown area
        self.pixbuf_offset_x = 0
        self.pixbuf_offset_y = 0
        self.pixbuf_offset_cmp_x = 0
        self.pixbuf_offset_cmp_y = 0
        self.pixbuf_x = 0
        self.pixbuf_y = 0
        self.pixbuf_w = self.AREA_WIDTH
        self.pixbuf_h = self.AREA_HEIGHT
        # the select box area
        self.edit_coord_x = 0
        self.edit_coord_y = 0
        self.edit_coord_w = self.AREA_WIDTH
        self.edit_coord_h = self.AREA_HEIGHT
        self.edit_coord_backup_x = 0
        self.edit_coord_backup_y = 0
        self.edit_coord_backup_w = self.AREA_WIDTH
        self.edit_coord_backup_h = self.AREA_HEIGHT

        self.drag_point_x = 0
        self.drag_point_y = 0
        self.__update_drag_point_coord()

    def draw_frame_border(self, widget, event):
        cr = widget.window.cairo_create()
        with cairo_disable_antialias(cr):
            cr.set_line_width(1)
            x, y, w, h = widget.allocation
            cr.set_source_rgb(*color_hex_to_cairo(TREEVIEW_BORDER_COLOR))
            cr.rectangle(x - 1, y - 1, w + 2, h + 2)
            cr.stroke()

    def on_camera_again_clicked_cb(self, button):
        self.set_camera_mode()

    def on_camera_clicked_cb(self, button):
        self.current_mode = self.MODE_CAMERA_EDIT
        drawable = self.camera_area.window
        colormap = drawable.get_colormap()
        pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 0, 8,
                                *drawable.get_size())
        pixbuf = pixbuf.get_from_drawable(drawable, colormap, 0, 0, 0, 0,
                                          *drawable.get_size())
        self.__edit_picture(pixbuf)
        container_remove_all(self.button_hbox)
        self.button_hbox.pack_start(self.button_zoom_in_align)
        self.button_hbox.pack_start(self.button_zoom_out_align)
        self.button_hbox.pack_start(self.button_camera_again_align)
        self.button_hbox.show_all()

    def on_zoom_in_clicked_cb(self, button):
        if self.pixbuf_w >= self.origin_pixbuf_width or self.pixbuf_h >= self.origin_pixbuf_height:
            print "has max size"
            button.set_sensitive(False)
            return
        width = int(self.pixbuf_w * 1.1)
        height = int(self.pixbuf_h * 1.1)
        if width >= self.origin_pixbuf_width:
            width = self.origin_pixbuf_width
        if height >= self.origin_pixbuf_height:
            height = self.origin_pixbuf_height
        self.cache_pixbuf.scale(self.origin_pixbuf, width, height)
        # count show area
        self.pixbuf_w = width
        self.pixbuf_h = height
        self.pixbuf_x = (self.AREA_WIDTH - width) / 2
        self.pixbuf_y = (self.AREA_HEIGHT - height) / 2
        if self.pixbuf_x < 0:
            self.pixbuf_offset_x -= self.pixbuf_x
            if self.pixbuf_offset_x + self.AREA_WIDTH > self.pixbuf_w:
                self.pixbuf_offset_x = self.pixbuf_w - self.AREA_WIDTH
            self.pixbuf_x = 0
        if self.pixbuf_y < 0:
            self.pixbuf_offset_y -= self.pixbuf_y
            if self.pixbuf_offset_y + self.AREA_HEIGHT > self.pixbuf_h:
                self.pixbuf_offset_y = self.pixbuf_h - self.AREA_HEIGHT
            self.pixbuf_y = 0
        self.__update_drag_point_coord()
        self.emit_changed()
        if self.pixbuf_w >= self.origin_pixbuf_width or self.pixbuf_h >= self.origin_pixbuf_height:
            button.set_sensitive(False)
        if not (self.pixbuf_w <= self.edit_coord_w or self.pixbuf_h <= self.edit_coord_h) \
                and not self.button_zoom_out.get_sensitive():
            self.button_zoom_out.set_sensitive(True)

    def on_zoom_out_clicked_cb(self, button):
        if self.edit_coord_w < self.MIN_SIZE or self.edit_coord_h < self.MIN_SIZE:
            self.edit_coord_w = self.edit_coord_h = self.MIN_SIZE
        if self.pixbuf_w <= self.edit_coord_w or self.pixbuf_h <= self.edit_coord_h:
            print "has min size"
            button.set_sensitive(False)
            return
        width = int(self.pixbuf_w * 0.9)
        height = int(self.pixbuf_h * 0.9)
        if height >= width and width <= self.edit_coord_w:
            height = int(float(height) / width * self.edit_coord_w)
            width = int(self.edit_coord_w)
        elif height < self.edit_coord_h:
            width = int(float(width) / height * self.edit_coord_h)
            height = int(self.edit_coord_h)
        self.cache_pixbuf.scale(self.origin_pixbuf, width, height)
        # count show area
        self.pixbuf_w = width
        self.pixbuf_h = height
        self.pixbuf_x = (self.AREA_WIDTH - width) / 2
        self.pixbuf_y = (self.AREA_HEIGHT - height) / 2
        # count pixbuf offset
        if self.pixbuf_x < 0:
            self.pixbuf_offset_x -= self.pixbuf_x
            if self.pixbuf_offset_x + self.AREA_WIDTH > self.pixbuf_w:
                self.pixbuf_offset_x = self.pixbuf_w - self.AREA_WIDTH
            self.pixbuf_x = 0
        if self.pixbuf_y < 0:
            self.pixbuf_offset_y -= self.pixbuf_y
            if self.pixbuf_offset_y + self.AREA_HEIGHT > self.pixbuf_h:
                self.pixbuf_offset_y = self.pixbuf_h - self.AREA_HEIGHT
            self.pixbuf_y = 0
        if self.pixbuf_x + self.pixbuf_w < self.AREA_WIDTH:
            self.pixbuf_offset_x = 0
        if self.pixbuf_y + self.pixbuf_h < self.AREA_HEIGHT:
            self.pixbuf_offset_y = 0
        # count edit area
        if self.edit_coord_x < self.pixbuf_x:
            self.edit_coord_x = self.pixbuf_x
        if self.edit_coord_y < self.pixbuf_y:
            self.edit_coord_y = self.pixbuf_y
        right_pos = min(self.pixbuf_x + self.pixbuf_w, self.AREA_WIDTH)
        bottom_pos = min(self.pixbuf_y + self.pixbuf_h, self.AREA_HEIGHT)
        if self.edit_coord_x + self.edit_coord_w > right_pos:
            self.edit_coord_x = right_pos - self.edit_coord_w
        if self.edit_coord_y + self.edit_coord_h > bottom_pos:
            self.edit_coord_y = bottom_pos - self.edit_coord_h
        self.__update_drag_point_coord()
        self.emit_changed()
        if self.pixbuf_w <= self.edit_coord_w or self.pixbuf_h <= self.edit_coord_h:
            button.set_sensitive(False)
        if not (self.pixbuf_w >= self.origin_pixbuf_width or self.pixbuf_h >= self.origin_pixbuf_height) \
                and not self.button_zoom_in.get_sensitive():
            self.button_zoom_in.set_sensitive(True)

    def __expose_edit(self, widget, event):
        pixbuf = self.cache_pixbuf.get_cache()
        if not pixbuf:
            return
        cr = widget.window.cairo_create()
        cr.set_source_pixbuf(pixbuf, self.pixbuf_x - self.pixbuf_offset_x,
                             self.pixbuf_y - self.pixbuf_offset_y)
        cr.paint()
        self.__draw_mask(cr, widget.allocation)
        self.__draw_frame(cr, widget.allocation)
        return True

    def __draw_frame(self, cr, allocation):
        with cairo_disable_antialias(cr):
            cr.set_line_width(1)
            cr.save()
            cr.set_dash((9, 3))
            cr.set_source_rgb(*color_hex_to_cairo(self.border_color))
            x = self.edit_coord_x
            y = self.edit_coord_y
            w = self.edit_coord_w
            h = self.edit_coord_h
            if x == 0:
                x = 1
            if y == 0:
                y = 1
            if x + w > self.AREA_WIDTH:
                w = self.AREA_WIDTH - x
            if y + h > self.AREA_HEIGHT:
                h = self.AREA_HEIGHT - y
            cr.rectangle(x, y, w, h)
            cr.stroke()

            cr.set_dash((3, 9))
            cr.set_source_rgb(1, 1, 1)
            cr.rectangle(x, y, w, h)
            cr.stroke()
            cr.restore()

            cr.set_source_rgb(*color_hex_to_cairo(self.border_color))
            cr.rectangle(self.drag_point_x, self.drag_point_y, self.DRAG_WIDTH,
                         self.DRAG_WIDTH)
            cr.stroke()

    def __draw_mask(self, cr, allocation):
        x, y, w, h = allocation
        x = 0
        y = 0
        # Draw left.
        if self.edit_coord_x > 0:
            cr.set_source_rgba(0, 0, 0, 0.5)
            cr.rectangle(x, y, self.edit_coord_x, h)
            cr.fill()

        # Draw top.
        if self.edit_coord_y > 0:
            cr.set_source_rgba(0, 0, 0, 0.5)
            cr.rectangle(x + self.edit_coord_x, y, w - self.edit_coord_x,
                         self.edit_coord_y)
            cr.fill()

        # Draw bottom.
        if self.edit_coord_y + self.edit_coord_h < h:
            cr.set_source_rgba(0, 0, 0, 0.5)
            cr.rectangle(x + self.edit_coord_x,
                         y + self.edit_coord_y + self.edit_coord_h,
                         w - self.edit_coord_x,
                         h - self.edit_coord_y - self.edit_coord_h)
            cr.fill()

        # Draw right.
        if self.edit_coord_x + self.edit_coord_w < w:
            cr.set_source_rgba(0, 0, 0, 0.5)
            cr.rectangle(x + self.edit_coord_x + self.edit_coord_w,
                         y + self.edit_coord_y,
                         w - self.edit_coord_x - self.edit_coord_w,
                         self.edit_coord_h)
            cr.fill()

    def set_pixbuf(self, pixbuf):
        if not pixbuf:
            self.cache_pixbuf.cache_pixbuf = None
            self.edit_area.queue_draw()
            self.emit_changed()
            self.button_zoom_in.set_sensitive(False)
            self.button_zoom_out.set_sensitive(False)
            return
        self.origin_pixbuf = pixbuf
        self.origin_pixbuf_width = w = pixbuf.get_width()
        self.origin_pixbuf_height = h = pixbuf.get_height()
        if h >= w:
            w = int(float(w) / h * self.AREA_HEIGHT)
            h = self.AREA_HEIGHT
            if w < self.MIN_SIZE:
                h = int(float(h) / w * self.MIN_SIZE)
                w = self.MIN_SIZE
            self.edit_coord_w = self.edit_coord_h = w
        else:
            h = int(float(h) / w * self.AREA_WIDTH)
            w = self.AREA_WIDTH
            if h < self.MIN_SIZE:
                w = int(float(w) / h * self.MIN_SIZE)
                h = self.MIN_SIZE
            self.edit_coord_w = self.edit_coord_h = h
        # count the offset coord
        self.pixbuf_offset_x = 0
        self.pixbuf_offset_y = 0
        self.pixbuf_x = 0
        self.pixbuf_y = 0
        self.pixbuf_w = w
        self.pixbuf_h = h
        if w < self.AREA_WIDTH:
            self.pixbuf_x = (self.AREA_WIDTH - w) / 2
        if h < self.AREA_HEIGHT:
            self.pixbuf_y = (self.AREA_HEIGHT - h) / 2
        # update select box coord
        self.edit_coord_x = self.pixbuf_x
        self.edit_coord_y = self.pixbuf_y
        self.cache_pixbuf.scale(pixbuf, w, h)
        ######
        self.edit_coord_w = self.edit_coord_h = self.MIN_SIZE
        self.edit_coord_x = self.edit_coord_y = (self.AREA_WIDTH -
                                                 self.MIN_SIZE) / 2
        ######
        self.drag_point_x = self.edit_coord_x + self.edit_coord_w - self.DRAG_WIDTH
        self.drag_point_y = self.edit_coord_y + self.edit_coord_h - self.DRAG_WIDTH
        self.edit_area.queue_draw()
        self.emit_changed()
        self.__update_button_sensitive()

    def emit_changed(self):
        pix = self.cache_pixbuf.get_cache()
        if pix:
            pix = pix.subpixbuf(
                int(self.edit_coord_x - self.pixbuf_x + self.pixbuf_offset_x),
                int(self.edit_coord_y - self.pixbuf_y + self.pixbuf_offset_y),
                int(self.edit_coord_w), int(self.edit_coord_h))
        self.emit("pixbuf-changed", pix)

    def get_pixbuf(self):
        return self.cache_pixbuf.get_cache()

    def set_cursor(self):
        if not self.edit_area.window:
            return
        if self.cursor_current != self.cursor[self.position]:
            self.cursor_current = self.cursor[self.position]
            self.edit_area.window.set_cursor(self.cursor_current)

    def __on_button_press_cb(self, widget, event):
        self.__update_position(event.x, event.y)
        if self.position == self.POS_IN_DRAG:
            self.drag_flag = True
        elif self.position == self.POS_IN_MOVE:
            self.move_flag = True
        self.press_point_coord = (event.x, event.y)
        self.edit_coord_backup_x = self.edit_coord_x
        self.edit_coord_backup_y = self.edit_coord_y
        self.edit_coord_backup_w = self.edit_coord_w
        self.edit_coord_backup_h = self.edit_coord_h

    def __on_button_release_cb(self, widget, event):
        self.drag_flag = False
        self.move_flag = False

    def __on_motion_notify_cb(self, widget, event):
        # if application window has not grab focus, return function
        if not self.camera_focus_flag:
            return
        x, y, w, h = widget.allocation
        if not self.drag_flag and not self.move_flag and \
                not self.panel.get_visible() and \
                y+self.AREA_HEIGHT-self.button_hbox_height<event.y<y+self.AREA_HEIGHT:
            self.slide_button_show(event)
            return
        pixbuf = self.cache_pixbuf.get_cache()
        if not pixbuf:
            return
        if not self.drag_flag and not self.move_flag:
            self.__update_position(event.x, event.y)
            self.set_cursor()
        right_pos = min(self.pixbuf_x + self.pixbuf_w, self.AREA_WIDTH)
        bottom_pos = min(self.pixbuf_y + self.pixbuf_h, self.AREA_HEIGHT)
        if self.move_flag:
            self.edit_coord_x = self.edit_coord_backup_x + event.x - self.press_point_coord[
                0]
            self.edit_coord_y = self.edit_coord_backup_y + event.y - self.press_point_coord[
                1]

            # check left
            if self.edit_coord_x < self.pixbuf_x:
                # move the pixbuf into canvas
                if self.pixbuf_w > self.AREA_WIDTH:
                    if self.pixbuf_offset_x > 0:
                        self.pixbuf_offset_x -= self.pixbuf_x - self.edit_coord_x
                    if self.pixbuf_offset_x < 0:
                        self.pixbuf_offset_x = 0
                self.edit_coord_x = self.pixbuf_x
            # check top
            if self.edit_coord_y < self.pixbuf_y:
                # move the pixbuf into canvas
                if self.pixbuf_h > self.AREA_HEIGHT:
                    if self.pixbuf_offset_y > 0:
                        self.pixbuf_offset_y -= self.pixbuf_y - self.edit_coord_y
                    if self.pixbuf_offset_y < 0:
                        self.pixbuf_offset_y = 0
                self.edit_coord_y = self.pixbuf_y
            # check right
            if self.edit_coord_x + self.edit_coord_w > right_pos:
                # move the pixbuf into canvas
                if self.pixbuf_w > self.AREA_WIDTH:
                    if self.pixbuf_offset_x + self.AREA_WIDTH < self.pixbuf_w:
                        self.pixbuf_offset_x += (
                            self.edit_coord_x +
                            self.edit_coord_w) - self.AREA_WIDTH
                    if self.pixbuf_offset_x + self.AREA_WIDTH > self.pixbuf_w:
                        self.pixbuf_offset_x = self.pixbuf_w - self.AREA_WIDTH
                self.edit_coord_x = right_pos - self.edit_coord_w
            # check bottom
            if self.edit_coord_y + self.edit_coord_h > bottom_pos:
                # move the pixbuf into canvas
                if self.pixbuf_h > self.AREA_HEIGHT:
                    if self.pixbuf_offset_y + self.AREA_HEIGHT < self.pixbuf_h:
                        self.pixbuf_offset_y += (
                            self.edit_coord_y +
                            self.edit_coord_h) - self.AREA_HEIGHT
                    if self.pixbuf_offset_y + self.AREA_HEIGHT > self.pixbuf_h:
                        self.pixbuf_offset_y = self.pixbuf_h - self.AREA_HEIGHT
                self.edit_coord_y = bottom_pos - self.edit_coord_h
        elif self.drag_flag:
            drag_offset = max(event.x - self.press_point_coord[0],
                              event.y - self.press_point_coord[1])
            self.edit_coord_h = self.edit_coord_w = self.edit_coord_backup_w + drag_offset
            if self.edit_coord_h < self.MIN_SIZE or self.edit_coord_w < self.MIN_SIZE:
                self.edit_coord_h = self.edit_coord_w = self.MIN_SIZE

            if self.edit_coord_x + self.edit_coord_w > right_pos:
                self.edit_coord_h = self.edit_coord_w = right_pos - self.edit_coord_x
            if self.edit_coord_y + self.edit_coord_h > bottom_pos:
                self.edit_coord_h = self.edit_coord_w = bottom_pos - self.edit_coord_y
            # check zoom_out button sensitive
            # if edit_area's size more than pixbuf size, then disable zoom_out button
            # else enable zoom_out button
            if not (self.pixbuf_w <= self.edit_coord_w
                    or self.pixbuf_h <= self.edit_coord_h):
                if not self.button_zoom_out.get_sensitive():
                    self.button_zoom_out.set_sensitive(True)
            else:
                if self.button_zoom_out.get_sensitive():
                    self.button_zoom_out.set_sensitive(False)
        self.__update_drag_point_coord()

    def __on_camera_motion_notify_cb(self, widget, event):
        if not self.camera_focus_flag:
            return
        x, y, w, h = widget.allocation
        #if not self.panel.get_visible() and \
        #y+self.AREA_HEIGHT-self.button_hbox_height<event.y<y+self.AREA_HEIGHT:
        if not self.panel.get_visible():
            if self.__refresh_time_id:
                gtk.timeout_remove(self.__refresh_time_id)
            if self.__button_time_id:
                gtk.timeout_remove(self.__button_time_id)
            self.__button_time_id = gobject.timeout_add(
                30, self.__slide_camera_button_show)
            #self.panel_layout.move(self.button_hbox, 0, self.button_hbox_height)
            x = event.x_root - event.x
            y = event.y_root - event.y - widget.allocation.y + self.AREA_HEIGHT - self.button_hbox_height
            self.set_win_pos(
                event.x_root - event.x - self.allocation.x, event.y_root -
                event.y - widget.allocation.y - self.allocation.y)
            self.panel.move(int(x), int(y) + self.button_hbox_height)
            self.panel.show_panel()

    def __draw_panel_background(self, widget, event):
        cr = widget.window.cairo_create()
        x, y, w, h = widget.allocation
        cr.set_source_rgb(0, 0, 0)
        cr.set_operator(OPERATOR_SOURCE)
        cr.paint()

        cr.set_source_rgba(0, 0, 0, 0.5)
        cr.rectangle(x, y, w, h)
        cr.paint()
        propagate_expose(widget, event)
        return True

    def __on_camera_expose_cb(self, widget, event):
        cr = widget.window.cairo_create()
        cr.set_source_rgb(0, 0, 0)
        cr.rectangle(0, 0, widget.allocation.width, widget.allocation.height)
        cr.fill()
        return True

    def __on_camera_enter_notify_cb(self, widget, event):
        pass

    def __on_camera_leave_notify_cb(self, widget, event):
        x, y, w, h = widget.allocation
        if (event.y_root == event.x_root == 0.0) or (x < event.x < x + w
                                                     and y < event.y < y + h):
            return
        if self.__button_time_id:
            gtk.timeout_remove(self.__button_time_id)
        self.__button_time_id = gobject.timeout_add(
            30, self.__slide_camera_button_hide)

    def __update_drag_point_coord(self):
        new_x = self.edit_coord_x + self.edit_coord_w - self.DRAG_WIDTH
        new_y = self.edit_coord_y + self.edit_coord_h - self.DRAG_WIDTH
        if self.drag_point_x != new_x or self.drag_point_y != new_y or\
                self.pixbuf_offset_cmp_x != self.pixbuf_offset_x or\
                self.pixbuf_offset_cmp_y != self.pixbuf_offset_y:
            self.drag_point_x = new_x
            self.drag_point_y = new_y
            self.pixbuf_offset_cmp_x = self.pixbuf_offset_x
            self.pixbuf_offset_cmp_y = self.pixbuf_offset_y
            self.emit_changed()
        self.edit_area.queue_draw()

    def __update_position(self, x, y):
        if self.drag_point_x <= x <= self.drag_point_x + self.DRAG_WIDTH and\
                self.drag_point_y <= y <= self.drag_point_y + self.DRAG_WIDTH:
            self.position = self.POS_IN_DRAG
        elif self.edit_coord_x <= x <= self.edit_coord_x + self.edit_coord_w and\
                self.edit_coord_y <= y <= self.edit_coord_y + self.edit_coord_h:
            self.position = self.POS_IN_MOVE
        else:
            self.position = self.POS_OUT

    def set_camera_mode(self):
        self.current_mode = self.MODE_CAMERA
        self.__camera_picture()
        self.__refresh_camera_button()

    def __camera_picture(self):
        self.set_pixbuf(None)
        if self.edit_area in self.box.get_children():
            self.box.remove(self.edit_area)
        if not self.camera_area_vbox in self.box.get_children():
            self.box.pack_start(self.camera_area_vbox, False, False)
            self.box.reorder_child(self.camera_area_vbox, 0)
        container_remove_all(self.button_hbox)
        self.button_hbox.pack_start(self.button_camera_align)
        self.button_hbox.show_all()
        self.show_all()
        try:
            if not self.camera_area.video_player:
                self.camera_area.create_video_pipeline()
            else:
                self.camera_start()
        except Exception, e:
            print e
예제 #4
0
    def __init__(self):
        super(IconEditArea, self).__init__()

        self.edit_area = gtk.EventBox()
        self.camera_area_vbox = gtk.VBox(False)
        self.camera_area = Webcam()
        self.camera_area_up = gtk.EventBox()
        self.camera_area_down = gtk.EventBox()
        self.camera_area_init_flag = False
        self.button_hbox = gtk.HBox(False)
        self.button_hbox_height = 40
        self.__widget_y = 92

        self.edit_area.set_size_request(self.AREA_WIDTH, self.AREA_HEIGHT)
        #self.camera_area.set_size_request(self.AREA_WIDTH, self.AREA_HEIGHT)
        self.camera_area_vbox.set_size_request(self.AREA_WIDTH,
                                               self.AREA_HEIGHT)
        self.camera_area.set_size_request(self.AREA_WIDTH, 225)
        #self.camera_area_up.set_size_request(self.AREA_WIDTH, 37)
        #self.camera_area_down.set_size_request(self.AREA_WIDTH, 37)
        self.button_hbox.set_size_request(self.AREA_WIDTH,
                                          self.button_hbox_height)

        self.button_zoom_in = ImageButton(
            app_theme.get_pixbuf("account/zoom_in.png"),
            app_theme.get_pixbuf("account/zoom_in.png"),
            app_theme.get_pixbuf("account/zoom_in.png"), _("zoom in"))
        self.button_zoom_out = ImageButton(
            app_theme.get_pixbuf("account/zoom_out.png"),
            app_theme.get_pixbuf("account/zoom_out.png"),
            app_theme.get_pixbuf("account/zoom_out.png"), _("zoom out"))
        self.button_camera = ImageButton(
            app_theme.get_pixbuf("account/camera.png"),
            app_theme.get_pixbuf("account/camera.png"),
            app_theme.get_pixbuf("account/camera.png"), _("Take a photo"))
        self.button_camera_again = ImageButton(
            app_theme.get_pixbuf("account/camera_again.png"),
            app_theme.get_pixbuf("account/camera_again.png"),
            app_theme.get_pixbuf("account/camera_again.png"), _("Try again"))

        self.button_zoom_in_align = tools.make_align(self.button_zoom_in,
                                                     xalign=0.5,
                                                     yalign=0.5)
        self.button_zoom_out_align = tools.make_align(self.button_zoom_out,
                                                      xalign=0.5,
                                                      yalign=0.5)
        self.button_camera_align = tools.make_align(self.button_camera,
                                                    xalign=0.5,
                                                    yalign=0.5)
        self.button_camera_again_align = tools.make_align(
            self.button_camera_again, xalign=0.5, yalign=0.5)

        self.button_zoom_in.connect("clicked", self.on_zoom_in_clicked_cb)
        self.button_zoom_out.connect("clicked", self.on_zoom_out_clicked_cb)
        self.button_camera.connect("clicked", self.on_camera_clicked_cb)
        self.button_camera_again.connect("clicked",
                                         self.on_camera_again_clicked_cb)

        self.box = gtk.VBox(False)
        self.box.pack_start(self.edit_area, False, False)
        #self.box.pack_start(self.button_hbox, False, False)
        #self.box.pack_start(tools.make_align(yalign=0.0, yscale=1.0))
        self.set_size(self.AREA_WIDTH, self.AREA_HEIGHT)
        self.set_size_request(self.AREA_WIDTH, self.AREA_HEIGHT)
        self.connect("expose-event", self.draw_frame_border)
        self.put(self.box, 0, 0)
        #self.put(self.button_hbox, 0, self.AREA_HEIGHT-self.button_hbox_height)

        self.edit_area.set_can_focus(True)
        self.edit_area.set_visible_window(False)
        self.edit_area.add_events(gtk.gdk.ALL_EVENTS_MASK)
        self.edit_area.connect("button-press-event", self.__on_button_press_cb)
        self.edit_area.connect("button-release-event",
                               self.__on_button_release_cb)
        self.edit_area.connect("motion-notify-event",
                               self.__on_motion_notify_cb)
        #self.edit_area.connect("leave-notify-event", self.__on_leave_notify_cb)
        self.edit_area.connect("expose-event", self.__expose_edit)

        self.camera_area_down.add_events(gtk.gdk.POINTER_MOTION_MASK)
        #self.camera_area.connect("motion-notify-event", self.__on_camera_motion_notify_cb)
        self.camera_area_down.connect("motion-notify-event",
                                      self.__on_camera_motion_notify_cb)
        self.camera_area_up.connect("expose-event", self.__on_camera_expose_cb)
        self.camera_area_down.connect("expose-event",
                                      self.__on_camera_expose_cb)
        self.camera_area_vbox.pack_start(self.camera_area_up)
        self.camera_area_vbox.pack_start(self.camera_area, False, False)
        self.camera_area_vbox.pack_start(self.camera_area_down)

        #panel_size = self.button_camera.get_size_request()
        #self.panel = Panel(panel_size[0], panel_size[1], gtk.WINDOW_POPUP)
        self.panel = Panel(self.AREA_WIDTH, self.button_hbox_height,
                           gtk.WINDOW_POPUP)
        self.panel_layout = gtk.Fixed()
        #self.panel_layout.put(self.button_camera_align, (self.AREA_WIDTH-panel_size[0])/2, 0)
        self.panel_layout.put(self.button_hbox, 0, 0)
        self.panel.add(self.panel_layout)
        self.panel.hide_panel()
        self.panel.connect("expose-event", self.__draw_panel_background)
        self.panel.connect("size-allocate", lambda w, e: w.queue_draw())

        #self.panel.connect("enter-notify-event", self.__on_camera_enter_notify_cb)
        self.panel.connect("leave-notify-event",
                           self.__on_camera_leave_notify_cb)
        self.camera_focus_flag = True

        self.__refresh_time_id = None
        self.__button_time_id = None
        self.current_mode = self.MODE_EDIT
        self.origin_pixbuf = None
        self.origin_pixbuf_width = 0
        self.origin_pixbuf_height = 0
        self.cache_pixbuf = CachePixbuf()
        self.border_color = "#000000"

        # cursor
        self.cursor = {
            self.POS_IN_DRAG: gtk.gdk.Cursor(gtk.gdk.BOTTOM_RIGHT_CORNER),
            self.POS_IN_MOVE: gtk.gdk.Cursor(gtk.gdk.FLEUR),
            self.POS_OUT: None
        }
        self.cursor_current = None

        self.press_point_coord = (0, 0)
        self.position = self.POS_OUT
        self.drag_flag = False
        self.move_flag = False
        #
        self.__show_button_flag = True
        self.__button_moving_flag = False
        #self.__refresh_flag = False

        # the pixbuf shown area
        self.pixbuf_offset_x = 0
        self.pixbuf_offset_y = 0
        self.pixbuf_offset_cmp_x = 0
        self.pixbuf_offset_cmp_y = 0
        self.pixbuf_x = 0
        self.pixbuf_y = 0
        self.pixbuf_w = self.AREA_WIDTH
        self.pixbuf_h = self.AREA_HEIGHT
        # the select box area
        self.edit_coord_x = 0
        self.edit_coord_y = 0
        self.edit_coord_w = self.AREA_WIDTH
        self.edit_coord_h = self.AREA_HEIGHT
        self.edit_coord_backup_x = 0
        self.edit_coord_backup_y = 0
        self.edit_coord_backup_w = self.AREA_WIDTH
        self.edit_coord_backup_h = self.AREA_HEIGHT

        self.drag_point_x = 0
        self.drag_point_y = 0
        self.__update_drag_point_coord()
예제 #5
0
 def __init__(self, width, height):
     '''Init test panel.'''
     Panel.__init__(self, width, height)
     
     self.connect_after("expose-event", self.expose_test_panel)