diff options
author | JRG 2 <jrg2@ubuntu.(none)> | 2013-12-20 00:45:24 (GMT) |
---|---|---|
committer | JRG 2 <jrg2@ubuntu.(none)> | 2013-12-20 00:45:24 (GMT) |
commit | 644b65d3dcb76db1c6269a17790891feefb5eeeb (patch) | |
tree | 0ac731d9663d86c49b53942c165d539d2f322724 | |
parent | b5fa8c2d65dec5d13ad1390f526129be2fb38bd3 (diff) |
Move backgroundmove_background
-rw-r--r-- | historietaactivity.py | 112 | ||||
-rw-r--r-- | persistencia.py | 15 | ||||
-rw-r--r-- | reorderwindow.py | 326 |
3 files changed, 418 insertions, 35 deletions
diff --git a/historietaactivity.py b/historietaactivity.py index e9e4e90..698a17f 100644 --- a/historietaactivity.py +++ b/historietaactivity.py @@ -22,6 +22,7 @@ from toolbar import GlobesManager from slideview import SlideView from reorderwindow import ReorderView +from reorderwindow import ImageEditorView import time from sugar3.datastore import datastore @@ -93,6 +94,12 @@ class HistorietaActivity(activity.Activity): toolbar_box.toolbar.insert(reorder_img_btn, -1) reorder_img_btn.show() + bgchange = ToolButton(icon_name='contract-coordinates') + bgchange.set_tooltip(_('Edit background image')) + bgchange.connect('clicked', self.__bgchange_clicked_cb) + toolbar_box.toolbar.insert(bgchange, -1) + bgchange.show() + separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) @@ -277,6 +284,10 @@ class HistorietaActivity(activity.Activity): reorderwin = ReorderView(self) reorderwin.show_all() + def __bgchange_clicked_cb(self, button): + editorwin = ImageEditorView(self.page.get_active_box()) + editorwin.show_all() + def _save_as_pdf(self, widget): file_name = os.path.join(self.get_activity_root(), 'instance', @@ -442,9 +453,9 @@ class Page(Gtk.VBox): self.pack_start(self._internal_box, True, True, 0) self.show_all() - def add_box_from_journal_image(self, image_file_name): + def add_box_from_journal_image(self, image_file_name, x=0, y=0, w=-1, h=-1): posi = len(self.boxs) - 1 - box = ComicBox(self, image_file_name, posi + 1) + box = ComicBox(self, image_file_name, posi + 1, x, y, w, h) reng = int(posi / 2) column = posi - (reng * 2) @@ -479,10 +490,16 @@ class Page(Gtk.VBox): class ComicBox(Gtk.EventBox): - def __init__(self, page, image_file_name, posi): + def __init__(self, page, image_file_name, posi, + x=0, y=0, width=0, height=0): print ('Cuadro INIT') Gtk.EventBox.__init__(self) + self.img_x = x + self.img_y = y + self.img_w = width + self.img_h = height + self._page = page self.modify_bg(Gtk.StateType.NORMAL, style.COLOR_WHITE.get_gdk_color()) @@ -626,40 +643,67 @@ class ComicBox(Gtk.EventBox): pixbuf = GdkPixbuf.Pixbuf.new_from_file(self.image_name) self.thumbnail = GdkPixbuf.Pixbuf.new_from_file_at_size( self.image_name, 200, 200) - width_pxb = pixbuf.get_width() - height_pxb = pixbuf.get_height() - scale = (self.width) / (1.0 * width_pxb) - self.image_height = int(scale * height_pxb) - self.image = ctx.get_target().create_similar( - cairo.CONTENT_COLOR_ALPHA, self.width, self.image_height) - - if (scale != 1): - # falta tener en cuenta el caso de una imagen - # que venga del journal y tenga el tamanio justo, - # es decir con scale = 1 - pixb_scaled = pixbuf.scale_simple( - int(self.width), - int(self.image_height), GdkPixbuf.InterpType.BILINEAR) - ct = cairo.Context(self.image) - Gdk.cairo_set_source_pixbuf(ct, pixb_scaled, 0, 0) - ct.paint() - if (not self.image_saved): - self.image_saved = True - # print instance_path - image_file_name = 'image' + str(self.posi) + '.png' - self.image.write_to_png(os.path.join(instance_path, - image_file_name)) - # grabamos el nombre de la imagen sin el path - self.image_name = image_file_name - else: - ct = cairo.Context(self.image) - Gdk.cairo_set_source_pixbuf(ct, pixbuf, 0, 0) - ct.paint() - self.image.flush() + img_scaled = False + if self.img_w == -1 and pixbuf.get_width() > self.width: + self.img_w = self.width + + width_pxb = pixbuf.get_width() + height_pxb = pixbuf.get_height() + scale = (self.width) / (1.0 * width_pxb) + self.img_h = int(scale * height_pxb) + img_scaled = True + elif self.img_w == -1 and pixbuf.get_width() == self.width: + self.img_w = self.width + self.img_h = pixbuf.get_height() + + + self.pixbuf = pixbuf + + self.image = ctx.get_target().create_similar( + cairo.CONTENT_COLOR_ALPHA, self.width, BOX_HEIGHT) + + pixb_scaled = pixbuf.scale_simple( + int(self.img_w), + int(self.img_h), GdkPixbuf.InterpType.BILINEAR) + ct = cairo.Context(self.image) + Gdk.cairo_set_source_pixbuf(ct, pixb_scaled, + self.img_x, self.img_y) + ct.paint() + + if (not self.image_saved) and img_scaled: + self.image_saved = True + # print instance_path + image_file_name = 'image' + str(self.posi) + '.png' + print "Grabamos: " + image_file_name + sav_img = ctx.get_target().create_similar( + cairo.CONTENT_COLOR_ALPHA, self.img_w, self.img_h) + ct2 = cairo.Context(sav_img) + Gdk.cairo_set_source_pixbuf(ct2, pixb_scaled, + 0, 0) + ct2.paint() + sav_img.write_to_png(os.path.join(instance_path, + image_file_name)) + img_scaled = False + + # grabamos el nombre de la imagen sin el path + self.image_name = image_file_name + + elif self._page.title_box != self: + self.image = ctx.get_target().create_similar( + cairo.CONTENT_COLOR_ALPHA, self.width, BOX_HEIGHT) + + pixb_scaled = self.pixbuf.scale_simple( + int(self.img_w), + int(self.img_h), GdkPixbuf.InterpType.BILINEAR) + ct = cairo.Context(self.image) + Gdk.cairo_set_source_pixbuf(ct, pixb_scaled, + self.img_x, self.img_y) + ct.paint() + if self.image is not None: ctx.save() - ctx.rectangle(0, 0, self.width, self.height) + ctx.rectangle(0, 0, self.width, BOX_HEIGHT) ctx.clip() ctx.set_source_surface(self.image, 0, 0) ctx.paint() diff --git a/persistencia.py b/persistencia.py index b6d6c0f..38220b3 100644 --- a/persistencia.py +++ b/persistencia.py @@ -39,6 +39,10 @@ class Persistence: pageData['boxs'] = [] for box in page.boxs: boxData = {} + boxData['img_x'] = box.img_x + boxData['img_y'] = box.img_y + boxData['img_w'] = box.img_w + boxData['img_h'] = box.img_h boxData['image_name'] = box.image_name boxData['globes'] = [] for globo in box.globos: @@ -125,7 +129,16 @@ class Persistence: for boxData in pageData['boxs']: if not primero: # el primero ya esta creado - page.add_box_from_journal_image(boxData['image_name']) + # para compatibilidad de versiones anteriores, + # verificamos si existe o no las nuevas propiedades + # en el archivo de persistencia + if boxData.has_key('img_x'): + page.add_box_from_journal_image(boxData['image_name'], + boxData['img_x'], boxData['img_y'], boxData['img_w'], + boxData['img_h']) + else: + page.add_box_from_journal_image(boxData['image_name'], + 0, 0, -1, -1) primero = False box = page.get_active_box() for globoData in boxData['globes']: diff --git a/reorderwindow.py b/reorderwindow.py index 5bb2f10..36c4d98 100644 --- a/reorderwindow.py +++ b/reorderwindow.py @@ -1,14 +1,46 @@ from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GObject +from gi.repository import GdkPixbuf from sugar3.graphics import style from sugar3.graphics.toolbutton import ToolButton from gi.repository.GdkPixbuf import Pixbuf +import cairo import gettext _ = lambda msg: gettext.dgettext('sugar', msg) +class UpdateToolbar(Gtk.Toolbar): + def __init__(self): + GObject.GObject.__init__(self) + + self.separator = Gtk.SeparatorToolItem() + self.separator.props.draw = False + self.separator.set_expand(True) + self.insert(self.separator, -1) + + self.stop = ToolButton(icon_name='dialog-cancel') + self.stop.set_tooltip(_('Cancel')) + self.insert(self.stop, -1) + self.stop.show() + + self.confirm = ToolButton(icon_name='dialog-ok') + self.confirm.set_tooltip(_('Done')) + self.insert(self.confirm, -1) + self.confirm.show() + + +class BaseWindow(Gtk.Window): + def __init__(self, width=400, height=400): + GObject.GObject.__init__(self) + self.set_border_width(style.LINE_WIDTH) + self.set_position(Gtk.WindowPosition.CENTER_ALWAYS) + self.set_decorated(False) + self.set_resizable(False) + self.set_size_request(height, width) + + class ReorderView(Gtk.Window): def __init__(self, activity): GObject.GObject.__init__(self) @@ -68,6 +100,7 @@ class ReorderObjects(Gtk.ScrolledWindow): self.iconview.set_model(self.liststore) self.iconview.set_pixbuf_column(0) self.iconview.set_reorderable(True) + #self.iconview.connect('item-activated', self.on_item_activated) for comicbox in self.comicboxes[1:]: try: @@ -77,6 +110,16 @@ class ReorderObjects(Gtk.ScrolledWindow): self.add(self.iconview) + def on_item_activated(self): + model = self.iconview.get_model() + pixbuf = model[self.iconview.get_selected_items()[0]][0] + for comicbox in self.comicboxes[1:]: + if pixbuf is comicbox.thumbnail: + self.editor = ImageEditorView(comicbox) + self.editor.show_all() + break + + def reorder_comicboxs(self): sorted_list = [] for row in self.liststore: @@ -95,3 +138,286 @@ class ReorderObjects(Gtk.ScrolledWindow): column = i - (reng * 2) self.activity.page.table.attach( self.comicboxes[i+1], column, column + 1, reng, reng + 1) + + +class ImageElement: + def __init__(self, pixbuf, box, x, y, w, h): + self.box = box + self.pixbuf = pixbuf + self.pixbuf_original = self.pixbuf.scale_simple( + self.pixbuf.get_width(), + self.pixbuf.get_height(), + GdkPixbuf.InterpType.BILINEAR) + self.x = x + self.y = y + self.width = w + self.height = h + self.calculate_boundaries() + self.calculate_points() + + def calculate_boundaries(self): + self.boundaries = {} + self.boundaries['min_x'] = self.x + self.boundaries['max_x'] = self.x + self.width + self.boundaries['min_y'] = self.y + self.boundaries['max_y'] = self.y + self.height + + def calculate_points(self): + self.points = {} + self.points["upper_left"] = [self.x, self.y] + self.points["upper_right"] = [self.x+self.width-18, self.y] + self.points["lower_left"] = [self.x, self.y+self.height - 18] + self.points["lower_right"] = [self.x+self.width-18, \ + self.y+self.height-18] + + def is_selected(self, x, y): + if (x >= self.boundaries['min_x'] and + x <= self.boundaries['max_x']) and \ + (y >= self.boundaries['min_y'] and + y <= self.boundaries['max_y']): + return True + else: + return False + + def is_resize(self, x, y): + if self.is_in_point(x, y): + return True + else: + return False + + def is_in_point(self, x, y, point=None): + if point is not None: + if (x >= point[0] and x <= (point[0]+18)) \ + and (y >= point[1] and y <= (point[1]+18)): + return True + else: + return False + else: + if self.is_in_point(x, y, self.points["upper_left"]) or \ + self.is_in_point(x, y, self.points["upper_right"]) or \ + self.is_in_point(x, y, self.points["lower_left"]) or \ + self.is_in_point(x, y, self.points["lower_right"]): + return True + else: + return False + + def draw(self, ctx): + self.image = ctx.get_target().create_similar( + cairo.CONTENT_COLOR_ALPHA, self.box.width, + self.box.height) + pixb_scaled = self.pixbuf_original.scale_simple( + self.width, self.height, + GdkPixbuf.InterpType.BILINEAR) + ct = cairo.Context(self.image) + Gdk.cairo_set_source_pixbuf(ct, pixb_scaled, self.x, + self.y) + ct.paint() + self.pixbuf = pixb_scaled + ctx.save() + ctx.rectangle(0, 0, self.box.width, self.box.height) + ctx.clip() + ctx.set_source_surface(self.image, 0, 0) + ctx.paint() + ctx.restore() + + def move(self, x_movement, y_movement, allocation): + self.x = self.x + x_movement + self.y = self.y + y_movement + + if self.x < 0: + self.x = 0 + if self.y < 0: + self.y = 0 + + if self.x + self.width > \ + allocation.width: + self.x -= (self.x + self.width) \ + - (allocation.width) + + if self.y + self.height > \ + allocation.height: + self.y -= (self.y + self.height) \ + - (allocation.height) + + self.calculate_boundaries() + self.calculate_points() + + def resize(self, x_movement, y_movement, allocation, + start_x, start_y): + + if self.is_in_point(start_x, start_y, + self.points["lower_left"]): + x_final_pos = self.x + x_movement + if x_final_pos < 0: + x_movement -= x_final_pos + self.x += x_movement + self.width -= x_movement + self.height += y_movement + elif self.is_in_point(start_x, start_y, + self.points["upper_right"]): + y_final_pos = self.y + y_movement + if y_final_pos < 0: + y_movement -= y_final_pos + self.y += y_movement + self.height -= y_movement + self.width += x_movement + elif self.is_in_point(start_x, start_y, + self.points["upper_left"]): + x_final_pos = self.x + x_movement + y_final_pos = self.y + y_movement + if x_final_pos < 0: + x_movement -= x_final_pos + if y_final_pos < 0: + y_movement -= y_final_pos + self.y += y_movement + self.x += x_movement + self.width -= x_movement + self.height -= y_movement + else: + self.height += y_movement + self.width += x_movement + + if self.width < 50: + self.width = 50 + if self.height < 50: + self.height = 50 + + if self.x + self.width > allocation.width: + self.width -= (self.x + self.width) \ + - (allocation.width) + + if self.y + self.height > allocation.height: + self.height -= (self.y + self.height) \ + - (allocation.height) + + self.calculate_boundaries() + self.calculate_points() + + +class CanvasEditor(Gtk.EventBox): + def __init__(self, comicbox, width, height, window): + Gtk.EventBox.__init__(self) + + self.width = width + self.height = height + self.is_resize = False + self.is_move = False + self.parentw = window + + self.modify_bg(Gtk.StateType.NORMAL, + style.COLOR_WHITE.get_gdk_color()) + self.fixed = Gtk.Fixed() + self.add(self.fixed) + self._drawingarea = Gtk.DrawingArea() + self.fixed.put(self._drawingarea, 0, 0) + + self._drawingarea.add_events( + Gdk.EventMask.POINTER_MOTION_MASK | + Gdk.EventMask.BUTTON_PRESS_MASK | + Gdk.EventMask.BUTTON_RELEASE_MASK | + Gdk.EventMask.BUTTON_MOTION_MASK) + + self.image = ImageElement(comicbox.pixbuf, self, + comicbox.img_x, comicbox.img_y, + comicbox.img_w, comicbox.img_h) + + self._drawingarea.connect("draw", self.draw_cb) + self.connect("button_press_event", self.pressing) + self.connect("motion_notify_event", self.mouse_move) + self.connect("motion_notify_event", self.moving) + self.connect("button_release_event", self.releassing) + self.redraw() + + def size_allocate(widget, allocation): + self.fixed.set_size_request(self.width, self.height) + self._drawingarea.set_size_request(self.width, self.height) + + self.connect('size_allocate', size_allocate) + self.set_size_request(self.width, self.height) + self.fixed.set_size_request(self.width, self.height) + self._drawingarea.set_size_request(self.width, self.height) + self.show_all() + + def redraw(self): + self._drawingarea.queue_draw() + + def draw_cb(self, widget, context): + self.draw_in_context(context) + + def draw_in_context(self, ctx): + self.image.draw(ctx) + + def pressing(self, widget, event): + if self.image.is_selected(event.x, event.y): + if self.image.is_in_point(event.x, event.y): + self.is_resize = True + self.is_move = False + else: + self.is_resize = False + self.is_move = True + self.start_x = event.x + self.start_y = event.y + + def mouse_move(self, widget, event): + cursor = None + if self.image.is_in_point(event.x, event.y): + cursor = Gdk.Cursor(Gdk.CursorType.SIZING) + elif self.image.is_selected(event.x, event.y): + cursor = Gdk.Cursor(Gdk.CursorType.HAND2) + self.get_window().set_cursor(cursor) + + def moving(self, widget, event): + if self.is_move: + x_movement = event.x - self.start_x + y_movement = event.y - self.start_y + self.image.move(x_movement, y_movement, self.get_allocation()) + self.start_x = event.x + self.start_y = event.y + self.redraw() + elif self.is_resize: + x_movement = event.x - self.start_x + y_movement = event.y - self.start_y + self.image.resize(x_movement, y_movement, self.get_allocation(), + self.start_x, self.start_y) + self.start_x = event.x + self.start_y = event.y + self.redraw() + + def releassing(self, widget, event): + self.is_resize = False + self.is_move = False + self.start_x = -1 + self.start_y = -1 + + +class ImageEditorView(BaseWindow): + def __init__(self, comicbox): + BaseWindow.__init__(self, comicbox.width, + comicbox.height) + + self.toolbar = UpdateToolbar() + self.toolbar.stop.connect( + 'clicked', self.__stop_clicked_cb) + self.toolbar.confirm.connect( + 'clicked', self.__ok_clicked_cb) + + self.comicbox = comicbox + self.canvas = CanvasEditor(self.comicbox, + self.comicbox.width, self.comicbox.height, + self) + + self.vbox = Gtk.VBox() + self.vbox.pack_start(self.toolbar, False, False, 0) + self.vbox.pack_start(self.canvas, True, True, 0) + self.add(self.vbox) + + def __stop_clicked_cb(self, button): + self.destroy() + + def __ok_clicked_cb(self, button): + self.comicbox.img_x = self.canvas.image.x + self.comicbox.img_y = self.canvas.image.y + self.comicbox.img_w = self.canvas.image.width + self.comicbox.img_h = self.canvas.image.height + self.comicbox.redraw() + self.destroy() |