Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGonzalo Odiard <godiard@gmail.com>2013-12-24 15:01:29 (GMT)
committer Gonzalo Odiard <godiard@gmail.com>2013-12-26 14:17:53 (GMT)
commitf9aadbee9a641139728cd8300f25c9fbfe68f3ee (patch)
tree924fa86c512b28b05ccdc255433576aaa9fed5fb
parent56704f14ecedcf80aefc59c0607652c40f579dff (diff)
Resize and move background image in a box - SL #2843
Signed-off-by: Jorge Alberto Gómez López <gomezlopez.jorge96@gmail.com> Reviewed-by: Gonzalo Odiard <gonzalo@laptop.org>
-rw-r--r--historietaactivity.py85
-rw-r--r--icons/contract-coordinates.svg79
-rw-r--r--persistencia.py14
-rw-r--r--po/POTFILES.in2
-rw-r--r--reorderwindow.py352
5 files changed, 509 insertions, 23 deletions
diff --git a/historietaactivity.py b/historietaactivity.py
index 3df015c..d23ae1b 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',
@@ -444,9 +455,10 @@ 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)
@@ -481,10 +493,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())
@@ -542,8 +560,7 @@ class ComicBox(Gtk.EventBox):
self.show_all()
def set_globo_activo(self, globo):
- if self._globo_activo is not None and \
- self._globo_activo != globo:
+ if self._globo_activo is not None and self._globo_activo != globo:
self._globo_activo.set_selected(False)
if globo is not None:
globo.set_selected(True)
@@ -625,6 +642,8 @@ class ComicBox(Gtk.EventBox):
os.path.join(instance_path, self.image_name))
else:
pixbuf = GdkPixbuf.Pixbuf.new_from_file(self.image_name)
+
+ """
width_pxb = pixbuf.get_width()
height_pxb = pixbuf.get_height()
scale = (self.width) / (1.0 * width_pxb)
@@ -655,6 +674,62 @@ class ComicBox(Gtk.EventBox):
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()
diff --git a/icons/contract-coordinates.svg b/icons/contract-coordinates.svg
new file mode 100644
index 0000000..1f704f3
--- /dev/null
+++ b/icons/contract-coordinates.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="55"
+ height="55"
+ id="svg2384">
+ <defs
+ id="defs2386" />
+ <rect
+ width="50"
+ height="50"
+ x="2.5"
+ y="2.5"
+ id="rect2394"
+ style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 27.333333,1 C 28.083333,50.75 27.333333,54 27.333333,54"
+ id="path3168"
+ style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 54,27.333333 C 4.2499997,28.083333 1,27.333333 1,27.333333"
+ id="path3170"
+ style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <g
+ transform="matrix(-1,0,0,-1,72.75,37.25)"
+ id="g3161"
+ style="stroke:#ffffff;stroke-opacity:1">
+ <path
+ d="M 28,27 L 37,18"
+ id="path2387"
+ style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 30,17 L 38,17 L 38,25"
+ id="path3159"
+ style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ transform="matrix(-1,0,0,1,72.75,18.25)"
+ id="g3167"
+ style="stroke:#ffffff;stroke-opacity:1">
+ <path
+ d="M 28,27 L 37,18"
+ id="path3169"
+ style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 30,17 L 38,17 L 38,25"
+ id="path3171"
+ style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ transform="matrix(1,0,0,-1,-18.25,37.25)"
+ id="g3173"
+ style="stroke:#ffffff;stroke-opacity:1">
+ <path
+ d="M 28,27 L 37,18"
+ id="path3175"
+ style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 30,17 L 38,17 L 38,25"
+ id="path3177"
+ style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+ <g
+ transform="translate(-18.25,18.25)"
+ id="g3179"
+ style="stroke:#ffffff;stroke-opacity:1">
+ <path
+ d="M 28,27 L 37,18"
+ id="path3181"
+ style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <path
+ d="M 30,17 L 38,17 L 38,25"
+ id="path3183"
+ style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ </g>
+</svg>
diff --git a/persistencia.py b/persistencia.py
index b6d6c0f..7e7f1d4 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,15 @@ 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 'img_x' in boxData:
+ 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'])
primero = False
box = page.get_active_box()
for globoData in boxData['globes']:
diff --git a/po/POTFILES.in b/po/POTFILES.in
index bfc3a55..adc0528 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -4,3 +4,5 @@ historietaactivity.py
persistencia.py
setup.py
toolbar.py
+reorderwindow.py
+fontcombobox.py
diff --git a/reorderwindow.py b/reorderwindow.py
index 7a50ebf..c179447 100644
--- a/reorderwindow.py
+++ b/reorderwindow.py
@@ -1,53 +1,76 @@
+import cairo
from gettext import gettext as _
from gi.repository import Gtk
from gi.repository import Gdk
from gi.repository import GObject
-from gi.repository.GdkPixbuf import Pixbuf
+from gi.repository import GdkPixbuf
from sugar3.graphics import style
from sugar3.graphics.toolbutton import ToolButton
+HANDLE_SIZE = 18
+MIN_IMAGE_SIZE = 50
-class ReorderView(Gtk.Window):
- def __init__(self, activity):
+
+class BaseWindow(Gtk.Window):
+
+ def __init__(self, width=-1, height=-1):
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)
- width = Gdk.Screen.width() - style.GRID_CELL_SIZE * 2
- height = Gdk.Screen.height() - style.GRID_CELL_SIZE * 2
+ if width == -1:
+ width = Gdk.Screen.width() - style.GRID_CELL_SIZE * 2
+ if height == -1:
+ height = Gdk.Screen.height() - style.GRID_CELL_SIZE * 2
self.set_size_request(width, height)
- self.set_default_size(width, height)
- self.toolbar = Gtk.Toolbar()
- icon = ToolButton('thumbs-view')
- self.toolbar.insert(icon, -1)
+class BasicToolbar(Gtk.Toolbar):
+
+ def __init__(self, icon_name, title):
+ GObject.GObject.__init__(self)
+
+ icon = ToolButton(icon_name)
+ self.insert(icon, -1)
label = Gtk.Label()
- title = _('Drag the images to reorder')
label.set_markup('<b>%s</b>' % title)
label.set_alignment(0, 0.5)
tool_item = Gtk.ToolItem()
tool_item.set_expand(True)
tool_item.add(label)
tool_item.show_all()
- self.toolbar.insert(tool_item, -1)
+ self.insert(tool_item, -1)
+
+ 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.stop.connect('clicked', self.__stop_clicked_cb)
- self.toolbar.insert(self.stop, -1)
+ self.insert(self.stop, -1)
self.stop.show()
self.confirm = ToolButton(icon_name='dialog-ok')
self.confirm.set_tooltip(_('Done'))
- self.confirm.connect('clicked', self.__ok_clicked_cb)
- self.toolbar.insert(self.confirm, -1)
+ self.insert(self.confirm, -1)
self.confirm.show()
+
+class ReorderView(BaseWindow):
+
+ def __init__(self, activity):
+ BaseWindow.__init__(self)
+ self.toolbar = BasicToolbar('thumbs-view',
+ _('Drag the images to reorder'))
+
+ self.toolbar.stop.connect('clicked', self.__stop_clicked_cb)
+ self.toolbar.confirm.connect('clicked', self.__ok_clicked_cb)
+
self.scrollwin = ReorderObjects(activity)
self.vbox = Gtk.VBox()
self.vbox.pack_start(self.toolbar, False, False, 0)
@@ -71,9 +94,8 @@ class ReorderObjects(Gtk.ScrolledWindow):
self.activity = activity
self.comicboxes = self.activity.page.boxs
- self.liststore = Gtk.ListStore(Pixbuf)
+ self.liststore = Gtk.ListStore(GdkPixbuf.Pixbuf)
self.iconview = Gtk.IconView.new()
- #self.iconview.set_columns(2)
self.iconview.set_property('item-width', 200)
self.iconview.set_model(self.liststore)
self.iconview.set_pixbuf_column(0)
@@ -84,6 +106,15 @@ 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:
@@ -102,3 +133,290 @@ 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 - HANDLE_SIZE,
+ self.y]
+ self.points["lower_left"] = [self.x,
+ self.y + self.height - HANDLE_SIZE]
+ self.points["lower_right"] = [self.x + self.width - HANDLE_SIZE,
+ self.y + self.height - HANDLE_SIZE]
+
+ 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] + HANDLE_SIZE)) \
+ and (y >= point[1] and y <= (point[1] + HANDLE_SIZE)):
+ 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()
+
+ # draw hadles
+ self._draw_handle(ctx, self.x, self.y)
+ self._draw_handle(ctx, self.x + self.width - HANDLE_SIZE,
+ self.y + self.height - HANDLE_SIZE)
+
+ def _draw_handle(self, ctx, x, y):
+ ctx.save()
+ ctx.set_line_width(2)
+ ctx.set_source_rgb(1, 1, 1)
+ ctx.rectangle(x, y, HANDLE_SIZE, HANDLE_SIZE)
+ ctx.stroke_preserve()
+ ctx.set_source_rgb(0, 0, 0)
+ ctx.set_dash([2])
+ ctx.stroke()
+ 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 < MIN_IMAGE_SIZE:
+ self.width = MIN_IMAGE_SIZE
+ if self.height < MIN_IMAGE_SIZE:
+ self.height = MIN_IMAGE_SIZE
+
+ 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.image.draw(context)
+
+ 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 + style.GRID_CELL_SIZE)
+
+ self.toolbar = BasicToolbar(
+ 'contract-coordinates',
+ _('Drag to move or resize using the marked corners'))
+ 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()