Skip to content

Commit

Permalink
Use handles to crop/scale the selection
Browse files Browse the repository at this point in the history
not 100% working yet
  • Loading branch information
maoschanz committed Sep 25, 2019
1 parent 1037a6a commit 09dd2b2
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 16 deletions.
2 changes: 1 addition & 1 deletion po/fr.po
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ msgstr "Sélection par couleur"

#: src/preferences.py:114 src/tools/classic_tools/tool_picker.py:12
msgid "Color Picker"
msgstr "Couleur"
msgstr "Sélecteur de couleur"

#: src/preferences.py:117 src/tools/classic_tools/tool_paint.py:14
msgid "Paint"
Expand Down
4 changes: 0 additions & 4 deletions src/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,10 +518,6 @@ def on_scroll_on_area(self, area, event):
else:
self.add_deltas(event.delta_x, event.delta_y, 10)

def get_dragged_selection_path(self):
# XXX and the zoom? TODO
return self.selection.get_path_with_scroll(self.scroll_x, self.scroll_y)

def on_scrollbar_value_change(self, scrollbar):
self.correct_coords(self.h_scrollbar.get_value(), self.v_scrollbar.get_value())
self.update()
Expand Down
19 changes: 16 additions & 3 deletions src/selection_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,13 @@ def delete_temp(self):
cairo_context.paint()
cairo_context.set_operator(cairo.Operator.OVER)

def get_path_with_scroll(self, scroll_x, scroll_y):
def get_path_with_scroll(self):
if self.selection_path is None:
return None
# XXX and the zoom? TODO
cairo_context = cairo.Context(self._get_surface())
delta_x = 0 - scroll_x + self.selection_x - self.temp_x
delta_y = 0 - scroll_y + self.selection_y - self.temp_y
delta_x = 0 - self.image.scroll_x + self.selection_x - self.temp_x
delta_y = 0 - self.image.scroll_y + self.selection_y - self.temp_y
for pts in self.selection_path:
if pts[1] is not ():
x = pts[1][0] + delta_x
Expand All @@ -155,6 +156,18 @@ def get_path_with_scroll(self, scroll_x, scroll_y):
cairo_context.close_path()
return cairo_context.copy_path()

def correct_coords(self, x1, x2, y1, y2, with_selection_coords):
x1 -= self.image.scroll_x
x2 -= self.image.scroll_x
y1 -= self.image.scroll_y
y2 -= self.image.scroll_y
if with_selection_coords:
x1 += self.selection_x
x2 += self.selection_x
y1 += self.selection_y
y2 += self.selection_y
return x1, x2, y1, y2

def show_selection_on_surface(self, cairo_context, with_scroll):
if self.selection_pixbuf is None:
return
Expand Down
2 changes: 1 addition & 1 deletion src/tools/abstract_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ def on_draw(self, area, cairo_context):
# Basic implementation, tools should do it better to fit their needs
if self.selection_is_active():
self.get_selection().show_selection_on_surface(cairo_context, True)
dragged_path = self.get_image().get_dragged_selection_path()
dragged_path = self.get_selection().get_path_with_scroll()
utilities_show_overlay_on_context(cairo_context, dragged_path, True)

############################################################################
Expand Down
24 changes: 21 additions & 3 deletions src/tools/canvas_tools/tool_crop.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from .bottombar import DrawingAdaptativeBottomBar

from .utilities import utilities_add_px_to_spinbutton
from .utilities import utilities_show_handles_on_context

class ToolCrop(AbstractCanvasTool):
__gtype_name__ = 'ToolCrop'
Expand Down Expand Up @@ -74,8 +75,10 @@ def init_if_selection(self):
def init_if_main(self):
self.original_width = self.get_image().get_pixbuf_width()
self.original_height = self.get_image().get_pixbuf_height()
self.width_btn.set_range(1, 10*self.original_width)
self.height_btn.set_range(1, 10*self.original_height)
self.width_btn.set_range(1, 10 * self.original_width)
self.height_btn.set_range(1, 10 * self.original_height)

############################################################################

def get_width(self):
return self.width_btn.get_value_as_int()
Expand All @@ -90,7 +93,6 @@ def on_height_changed(self, *args):
self.update_temp_pixbuf()

def on_unclicked_motion_on_area(self, event, surface):
print('93', event)
cursor_name = ''
if event.y < 0.3 * surface.get_height():
cursor_name = cursor_name + 'n'
Expand Down Expand Up @@ -161,6 +163,22 @@ def move_west(self, delta):
def on_release_on_area(self, event, surface, event_x, event_y):
self.window.set_cursor(False)

############################################################################

def on_draw(self, area, cairo_context):
if self.apply_to_selection:
# print('on_draw: yes')
x1 = int(self._x)
y1 = int(self._y)
x2 = x1 + self.get_width()
y2 = y1 + self.get_height()
x1, x2, y1, y2 = self.get_selection().correct_coords(x1, x2, y1, y2, True)
utilities_show_handles_on_context(cairo_context, x1, x2, y1, y2)
# else:
# print('on_draw: no')

############################################################################

def crop_temp_pixbuf(self, x, y, width, height, is_selection):
new_pixbuf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, width, height)
new_pixbuf.fill(0)
Expand Down
19 changes: 19 additions & 0 deletions src/tools/canvas_tools/tool_scale.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from .bottombar import DrawingAdaptativeBottomBar

from .utilities import utilities_add_px_to_spinbutton
from .utilities import utilities_show_handles_on_context

class ToolScale(AbstractCanvasTool):
__gtype_name__ = 'ToolScale'
Expand Down Expand Up @@ -97,6 +98,8 @@ def get_width(self):
def get_height(self):
return self.height_btn.get_value_as_int()

############################################################################

def on_press_on_area(self, event, surface, event_x, event_y):
self.x_press = event.x
self.y_press = event.y
Expand All @@ -113,6 +116,22 @@ def on_motion_on_area(self, event, surface, event_x, event_y):
def on_release_on_area(self, event, surface, event_x, event_y):
self.on_motion_on_area(event, surface, event_x, event_y)

############################################################################

def on_draw(self, area, cairo_context):
if self.apply_to_selection:
# print('on_draw: yes')
x1 = self.get_selection().selection_x # XXX
y1 = self.get_selection().selection_y # XXX
x2 = x1 + self.get_width()
y2 = y1 + self.get_height()
x1, x2, y1, y2 = self.get_selection().correct_coords(x1, x2, y1, y2, False)
utilities_show_handles_on_context(cairo_context, x1, x2, y1, y2)
# else:
# print('on_draw: no')

############################################################################

def build_operation(self):
operation = {
'tool_id': self.id,
Expand Down
5 changes: 3 additions & 2 deletions src/tools/classic_tools/tool_shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,9 @@ def draw_oval(self, event_x, event_y):

def draw_circle(self, event_x, event_y):
cairo_context = cairo.Context(self.get_surface())
rayon = math.sqrt((self.x_press - event_x)*(self.x_press - event_x) \
+ (self.y_press - event_y)*(self.y_press - event_y))
delta_x2 = (self.x_press - event_x) * (self.x_press - event_x)
delta_y2 = (self.y_press - event_y) * (self.y_press - event_y)
rayon = math.sqrt(delta_x2 + delta_y2)
cairo_context.arc(self.x_press, self.y_press, rayon, 0.0, 2*math.pi)
self._path = cairo_context.copy_path()

Expand Down
65 changes: 63 additions & 2 deletions src/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,73 @@ def utilities_show_overlay_on_context(cairo_context, cairo_path, has_dashes):
if cairo_path is None:
return
cairo_context.new_path()
cairo_context.set_line_width(1)
if has_dashes:
cairo_context.set_dash([3, 3])
cairo_context.append_path(cairo_path)
cairo_context.clip_preserve()
cairo_context.set_source_rgba(0.1, 0.1, 0.3, 0.2)
cairo_context.paint()
cairo_context.fill_preserve()
cairo_context.set_source_rgba(0.5, 0.5, 0.5, 0.5)
cairo_context.stroke()

def utilities_show_handles_on_context(cairo_context, x1, x2, y1, y2):
rayon = min([(x2 - x1)/5, (y2 - y1)/5, 12])
height_h = True # XXX

_draw_arc_handle(cairo_context, x1, y1, rayon, 'nw')
_draw_arc_handle(cairo_context, x2, y1, rayon, 'ne')
_draw_arc_handle(cairo_context, x2, y2, rayon, 'se')
_draw_arc_handle(cairo_context, x1, y2, rayon, 'sw')
if height_h:
_draw_arc_handle(cairo_context, (x1+x2)/2, y1, rayon, 'n')
_draw_arc_handle(cairo_context, x2, (y1+y2)/2, rayon, 'e')
_draw_arc_handle(cairo_context, (x1+x2)/2, y2, rayon, 's')
_draw_arc_handle(cairo_context, x1, (y1+y2)/2, rayon, 'w')

cairo_context.move_to(x1, y1)
cairo_context.line_to(x1, y2)
cairo_context.line_to(x2, y2)
cairo_context.line_to(x2, y1)
cairo_context.close_path()

cairo_context.set_line_width(1)
cairo_context.set_dash([2, 2])
cairo_context.set_source_rgba(0.5, 0.5, 0.5, 0.5)
cairo_context.stroke()

def _draw_arc_handle(cairo_context, x, y, rayon, orientation):
if orientation == 'nw':
angle_1 = 0.5 * math.pi
angle_2 = 2.0 * math.pi
elif orientation == 'n':
angle_1 = math.pi
angle_2 = 0.0
elif orientation == 'ne':
angle_1 = math.pi
angle_2 = 0.5 * math.pi
elif orientation == 'e':
angle_1 = -0.5 * math.pi
angle_2 = 0.5 * math.pi
elif orientation == 'se':
angle_1 = -0.5 * math.pi
angle_2 = math.pi
elif orientation == 's':
angle_1 = 0.0
angle_2 = math.pi
elif orientation == 'sw':
angle_1 = 0.0
angle_2 = -0.5 * math.pi
elif orientation == 'w':
angle_1 = 0.5 * math.pi
angle_2 = -0.5 * math.pi

cairo_context.move_to(x, y)
cairo_context.arc(x, y, rayon, angle_1, angle_2)
cairo_context.close_path()

cairo_context.set_line_width(3)
cairo_context.set_source_rgba(1.0, 1.0, 1.0, 1.0)
cairo_context.fill_preserve()
cairo_context.set_source_rgba(0.5, 0.5, 0.5, 0.5)
cairo_context.stroke()

Expand Down

1 comment on commit 09dd2b2

@maoschanz
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

related to #85, #23, and #21

Please sign in to comment.