301 lines
9.4 KiB
Python
301 lines
9.4 KiB
Python
#
|
|
# Gramps - a GTK+/GNOME based genealogy program
|
|
#
|
|
# Copyright (C) 2013 Artem Glebov <artem.glebov@gmail.com>
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
#
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# GTK/Gnome modules
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
from gi.repository import Gdk
|
|
|
|
#-------------------------------------------------------------------------
|
|
#
|
|
# grabbers constants and routines
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
|
|
GRABBER_INSIDE = 0
|
|
GRABBER_OUTSIDE = 1
|
|
|
|
MIN_CORNER_GRABBER = 20
|
|
MIN_SIDE_GRABBER = 20
|
|
MIN_GRABBER_PADDING = 10
|
|
MIN_SIDE_FOR_INSIDE_GRABBERS = (2 * (MIN_CORNER_GRABBER + MIN_GRABBER_PADDING) +
|
|
MIN_SIDE_GRABBER)
|
|
|
|
INSIDE = 0
|
|
GRABBER_UPPER_LEFT = 1
|
|
GRABBER_UPPER = 2
|
|
GRABBER_UPPER_RIGHT = 3
|
|
GRABBER_RIGHT = 4
|
|
GRABBER_LOWER_RIGHT = 5
|
|
GRABBER_LOWER = 6
|
|
GRABBER_LOWER_LEFT = 7
|
|
GRABBER_LEFT = 8
|
|
|
|
def upper_left_grabber_inner(x1, y1, x2, y2):
|
|
return (x1, y1, x1 + MIN_CORNER_GRABBER, y1 + MIN_CORNER_GRABBER)
|
|
|
|
def upper_grabber_inner(x1, y1, x2, y2):
|
|
return (x1 + MIN_CORNER_GRABBER + MIN_GRABBER_PADDING,
|
|
y1,
|
|
x2 - MIN_CORNER_GRABBER - MIN_GRABBER_PADDING,
|
|
y1 + MIN_CORNER_GRABBER)
|
|
|
|
def upper_right_grabber_inner(x1, y1, x2, y2):
|
|
return (x2 - MIN_CORNER_GRABBER, y1, x2, y1 + MIN_CORNER_GRABBER)
|
|
|
|
def right_grabber_inner(x1, y1, x2, y2):
|
|
return (x2 - MIN_CORNER_GRABBER,
|
|
y1 + MIN_CORNER_GRABBER + MIN_GRABBER_PADDING,
|
|
x2,
|
|
y2 - MIN_CORNER_GRABBER - MIN_GRABBER_PADDING)
|
|
|
|
def lower_right_grabber_inner(x1, y1, x2, y2):
|
|
return (x2 - MIN_CORNER_GRABBER, y2 - MIN_CORNER_GRABBER, x2, y2)
|
|
|
|
def lower_grabber_inner(x1, y1, x2, y2):
|
|
return (x1 + MIN_CORNER_GRABBER + MIN_GRABBER_PADDING,
|
|
y2 - MIN_CORNER_GRABBER,
|
|
x2 - MIN_CORNER_GRABBER - MIN_GRABBER_PADDING,
|
|
y2)
|
|
|
|
def lower_left_grabber_inner(x1, y1, x2, y2):
|
|
return (x1, y2 - MIN_CORNER_GRABBER, x1 + MIN_CORNER_GRABBER, y2)
|
|
|
|
def left_grabber_inner(x1, y1, x2, y2):
|
|
return (x1,
|
|
y1 + MIN_CORNER_GRABBER + MIN_GRABBER_PADDING,
|
|
x1 + MIN_CORNER_GRABBER,
|
|
y2 - MIN_CORNER_GRABBER - MIN_GRABBER_PADDING)
|
|
|
|
# outer
|
|
|
|
def upper_left_grabber_outer(x1, y1, x2, y2):
|
|
return (x1 - MIN_CORNER_GRABBER, y1 - MIN_CORNER_GRABBER, x1, y1)
|
|
|
|
def upper_grabber_outer(x1, y1, x2, y2):
|
|
return (x1, y1 - MIN_CORNER_GRABBER, x2, y1)
|
|
|
|
def upper_right_grabber_outer(x1, y1, x2, y2):
|
|
return (x2, y1 - MIN_CORNER_GRABBER, x2 + MIN_CORNER_GRABBER, y1)
|
|
|
|
def right_grabber_outer(x1, y1, x2, y2):
|
|
return (x2, y1, x2 + MIN_CORNER_GRABBER, y2)
|
|
|
|
def lower_right_grabber_outer(x1, y1, x2, y2):
|
|
return (x2, y2, x2 + MIN_CORNER_GRABBER, y2 + MIN_CORNER_GRABBER)
|
|
|
|
def lower_grabber_outer(x1, y1, x2, y2):
|
|
return (x1, y2, x2, y2 + MIN_CORNER_GRABBER)
|
|
|
|
def lower_left_grabber_outer(x1, y1, x2, y2):
|
|
return (x1 - MIN_CORNER_GRABBER, y2, x1, y2 + MIN_CORNER_GRABBER)
|
|
|
|
def left_grabber_outer(x1, y1, x2, y2):
|
|
return (x1 - MIN_CORNER_GRABBER, y1, x1, y2)
|
|
|
|
# motion
|
|
|
|
def inside_moved(x1, y1, x2, y2, dx, dy):
|
|
return (x1, y1, x2, y2)
|
|
|
|
def upper_left_moved(x1, y1, x2, y2, dx, dy):
|
|
return (x1 + dx, y1 + dy, x2, y2)
|
|
|
|
def upper_moved(x1, y1, x2, y2, dx, dy):
|
|
return (x1, y1 + dy, x2, y2)
|
|
|
|
def upper_right_moved(x1, y1, x2, y2, dx, dy):
|
|
return (x1, y1 + dy, x2 + dx, y2)
|
|
|
|
def right_moved(x1, y1, x2, y2, dx, dy):
|
|
return (x1, y1, x2 + dx, y2)
|
|
|
|
def lower_right_moved(x1, y1, x2, y2, dx, dy):
|
|
return (x1, y1, x2 + dx, y2 + dy)
|
|
|
|
def lower_moved(x1, y1, x2, y2, dx, dy):
|
|
return (x1, y1, x2, y2 + dy)
|
|
|
|
def lower_left_moved(x1, y1, x2, y2, dx, dy):
|
|
return (x1 + dx, y1, x2, y2 + dy)
|
|
|
|
def left_moved(x1, y1, x2, y2, dx, dy):
|
|
return (x1 + dx, y1, x2, y2)
|
|
|
|
# switching
|
|
|
|
GRABBERS = [INSIDE,
|
|
GRABBER_UPPER_LEFT,
|
|
GRABBER_UPPER,
|
|
GRABBER_UPPER_RIGHT,
|
|
GRABBER_RIGHT,
|
|
GRABBER_LOWER_RIGHT,
|
|
GRABBER_LOWER,
|
|
GRABBER_LOWER_LEFT,
|
|
GRABBER_LEFT]
|
|
|
|
INNER_GRABBERS = [None,
|
|
upper_left_grabber_inner,
|
|
upper_grabber_inner,
|
|
upper_right_grabber_inner,
|
|
right_grabber_inner,
|
|
lower_right_grabber_inner,
|
|
lower_grabber_inner,
|
|
lower_left_grabber_inner,
|
|
left_grabber_inner]
|
|
|
|
OUTER_GRABBERS = [None,
|
|
upper_left_grabber_outer,
|
|
upper_grabber_outer,
|
|
upper_right_grabber_outer,
|
|
right_grabber_outer,
|
|
lower_right_grabber_outer,
|
|
lower_grabber_outer,
|
|
lower_left_grabber_outer,
|
|
left_grabber_outer]
|
|
|
|
MOTION_FUNCTIONS = [inside_moved,
|
|
upper_left_moved,
|
|
upper_moved,
|
|
upper_right_moved,
|
|
right_moved,
|
|
lower_right_moved,
|
|
lower_moved,
|
|
lower_left_moved,
|
|
left_moved]
|
|
|
|
GRABBERS_SWITCH = [
|
|
[INSIDE, INSIDE, INSIDE],
|
|
[GRABBER_UPPER_RIGHT, GRABBER_LOWER_RIGHT, GRABBER_LOWER_LEFT],
|
|
[GRABBER_UPPER, GRABBER_LOWER, GRABBER_LOWER],
|
|
[GRABBER_UPPER_LEFT, GRABBER_LOWER_LEFT, GRABBER_LOWER_RIGHT],
|
|
[GRABBER_LEFT, GRABBER_LEFT, GRABBER_RIGHT],
|
|
[GRABBER_LOWER_LEFT, GRABBER_UPPER_LEFT, GRABBER_UPPER_RIGHT],
|
|
[GRABBER_LOWER, GRABBER_UPPER, GRABBER_UPPER],
|
|
[GRABBER_LOWER_RIGHT, GRABBER_UPPER_RIGHT, GRABBER_UPPER_LEFT],
|
|
[GRABBER_RIGHT, GRABBER_RIGHT, GRABBER_LEFT]
|
|
]
|
|
|
|
# cursors
|
|
try:
|
|
CURSOR_UPPER = \
|
|
Gdk.Cursor.new_for_display(Gdk.Display.get_default(),
|
|
Gdk.CursorType.TOP_SIDE)
|
|
CURSOR_LOWER = \
|
|
Gdk.Cursor.new_for_display(Gdk.Display.get_default(),
|
|
Gdk.CursorType.BOTTOM_SIDE)
|
|
CURSOR_LEFT = \
|
|
Gdk.Cursor.new_for_display(Gdk.Display.get_default(),
|
|
Gdk.CursorType.LEFT_SIDE)
|
|
CURSOR_RIGHT = \
|
|
Gdk.Cursor.new_for_display(Gdk.Display.get_default(),
|
|
Gdk.CursorType.RIGHT_SIDE)
|
|
CURSOR_UPPER_LEFT = \
|
|
Gdk.Cursor.new_for_display(Gdk.Display.get_default(),
|
|
Gdk.CursorType.TOP_LEFT_CORNER)
|
|
CURSOR_UPPER_RIGHT = \
|
|
Gdk.Cursor.new_for_display(Gdk.Display.get_default(),
|
|
Gdk.CursorType.TOP_RIGHT_CORNER)
|
|
CURSOR_LOWER_LEFT = \
|
|
Gdk.Cursor.new_for_display(Gdk.Display.get_default(),
|
|
Gdk.CursorType.BOTTOM_LEFT_CORNER)
|
|
CURSOR_LOWER_RIGHT = \
|
|
Gdk.Cursor.new_for_display(Gdk.Display.get_default(),
|
|
Gdk.CursorType.BOTTOM_RIGHT_CORNER)
|
|
except:
|
|
CURSOR_UPPER = None
|
|
CURSOR_LOWER = None
|
|
CURSOR_LEFT = None
|
|
CURSOR_RIGHT = None
|
|
CURSOR_UPPER_LEFT = None
|
|
CURSOR_UPPER_RIGHT = None
|
|
CURSOR_LOWER_LEFT = None
|
|
CURSOR_LOWER_RIGHT = None
|
|
|
|
CURSORS = [None,
|
|
CURSOR_UPPER_LEFT,
|
|
CURSOR_UPPER,
|
|
CURSOR_UPPER_RIGHT,
|
|
CURSOR_RIGHT,
|
|
CURSOR_LOWER_RIGHT,
|
|
CURSOR_LOWER,
|
|
CURSOR_LOWER_LEFT,
|
|
CURSOR_LEFT]
|
|
|
|
# helper functions
|
|
|
|
def grabber_position(rect):
|
|
x1, y1, x2, y2 = rect
|
|
if (x2 - x1 >= MIN_SIDE_FOR_INSIDE_GRABBERS and
|
|
y2 - y1 >= MIN_SIDE_FOR_INSIDE_GRABBERS):
|
|
return GRABBER_INSIDE
|
|
else:
|
|
return GRABBER_OUTSIDE
|
|
|
|
def grabber_generators(rect):
|
|
if grabber_position(rect) == GRABBER_INSIDE:
|
|
return INNER_GRABBERS
|
|
else:
|
|
return OUTER_GRABBERS
|
|
|
|
def switch_grabber(grabber, x1, y1, x2, y2):
|
|
switch_row = GRABBERS_SWITCH[grabber]
|
|
if x1 > x2:
|
|
if y1 > y2:
|
|
return switch_row[1]
|
|
else:
|
|
return switch_row[0]
|
|
else:
|
|
if y1 > y2:
|
|
return switch_row[2]
|
|
else:
|
|
return grabber
|
|
|
|
def inside_rect(rect, x, y):
|
|
x1, y1, x2, y2 = rect
|
|
return x1 <= x <= x2 and y1 <= y <= y2
|
|
|
|
def can_grab(rect, x, y):
|
|
"""
|
|
Checks if (x,y) lies within one of the grabbers of rect.
|
|
"""
|
|
(x1, y1, x2, y2) = rect
|
|
if (x2 - x1 >= MIN_SIDE_FOR_INSIDE_GRABBERS and
|
|
y2 - y1 >= MIN_SIDE_FOR_INSIDE_GRABBERS):
|
|
# grabbers are inside
|
|
if x < x1 or x > x2 or y < y1 or y > y2:
|
|
return None
|
|
for grabber in GRABBERS[1:]:
|
|
grabber_area = INNER_GRABBERS[grabber](x1, y1, x2, y2)
|
|
if inside_rect(grabber_area, x, y):
|
|
return grabber
|
|
return INSIDE
|
|
else:
|
|
# grabbers are outside
|
|
if x1 <= x <= x2 and y1 <= y <= y2:
|
|
return INSIDE
|
|
for grabber in GRABBERS[1:]:
|
|
grabber_area = OUTER_GRABBERS[grabber](x1, y1, x2, y2)
|
|
if inside_rect(grabber_area, x, y):
|
|
return grabber
|
|
return None
|