Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/sugar
diff options
context:
space:
mode:
authorMarco Pesenti Gritti <mpg@redhat.com>2007-09-01 09:59:16 (GMT)
committer Marco Pesenti Gritti <mpg@redhat.com>2007-09-01 09:59:16 (GMT)
commit8a3c2a58433d140ea350081ade77f992ed57ef4b (patch)
treedc0d7b2931e80a307dd068505d059f81b92f1e36 /sugar
parentbd9bd2d020e13579d24e816b73f053da78e23739 (diff)
More palette positioning improvements.
Diffstat (limited to 'sugar')
-rw-r--r--sugar/graphics/palette.py225
1 files changed, 110 insertions, 115 deletions
diff --git a/sugar/graphics/palette.py b/sugar/graphics/palette.py
index 4c52421..bc2513c 100644
--- a/sugar/graphics/palette.py
+++ b/sugar/graphics/palette.py
@@ -27,16 +27,6 @@ from sugar.graphics import animator
from sugar.graphics import style
from sugar import _sugaruiext
-_BOTTOM_LEFT = 0
-_BOTTOM_RIGHT = 1
-_LEFT_BOTTOM = 2
-_LEFT_TOP = 3
-_RIGHT_BOTTOM = 4
-_RIGHT_TOP = 5
-_TOP_LEFT = 6
-_TOP_RIGHT = 7
-
-
# Helper function to find the gap position and size of widget a
def _calculate_gap(a, b):
# Test for each side if the palette and invoker are
@@ -70,10 +60,6 @@ def _calculate_gap(a, b):
return False
class Palette(gtk.Window):
- DEFAULT = 0
- AT_CURSOR = 1
- AROUND = 2
-
PRIMARY = 0
SECONDARY = 1
@@ -102,7 +88,7 @@ class Palette(gtk.Window):
self.palette_state = self.PRIMARY
- self._current_alignment = None
+ self._alignment = None
self._old_alloc = None
self._full_request = [0, 0]
self._cursor_x = 0
@@ -110,7 +96,6 @@ class Palette(gtk.Window):
self._invoker = None
self._group_id = None
self._up = False
- self._position = self.DEFAULT
self._palette_popup_sid = None
self._popup_anim = animator.Animator(0.3, 10)
@@ -203,16 +188,12 @@ class Palette(gtk.Window):
self._invoker = value
self._invoker.connect('mouse-enter', self._invoker_mouse_enter_cb)
self._invoker.connect('mouse-leave', self._invoker_mouse_leave_cb)
- elif pspec.name == 'position':
- self._position = value
else:
raise AssertionError
def do_get_property(self, pspec):
if pspec.name == 'invoker':
return self._invoker
- elif pspec.name == 'position':
- return self._position
else:
raise AssertionError
@@ -275,52 +256,6 @@ class Palette(gtk.Window):
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
self._update_accept_focus()
- def _in_screen(self, rect):
- screen_area = self._invoker.get_screen_area()
- return rect.x >= screen_area.x and \
- rect.y >= screen_area.y and \
- rect.x + rect.width <= screen_area.width and \
- rect.y + rect.height <= screen_area.height
-
- def _get_rectangle(self, alignments, full=False, inv_rect=None):
- palette_halign = alignments[0]
- palette_valign = alignments[1]
- invoker_halign = alignments[2]
- invoker_valign = alignments[3]
-
- if inv_rect == None:
- inv_rect = self._invoker.get_rect()
-
- if full:
- palette_width, palette_height = self._full_request
- else:
- palette_width, palette_height = self.size_request()
-
- x = inv_rect.x + inv_rect.width * invoker_halign + \
- palette_width * palette_halign
-
- y = inv_rect.y + inv_rect.height * invoker_valign + \
- palette_height * palette_valign
-
- return gtk.gdk.Rectangle(int(x), int(y),
- palette_width, palette_height)
-
- def _get_around_alignments(self):
- return [(0.0, 0.0, 0.0, 1.0),
- (-1.0, 0.0, 1.0, 1.0),
- (0.0, 0.0, 1.0, 0.0),
- (0.0, -1.0, 1.0, 1.0),
- (0.0, -1.0, 0.0, 0.0),
- (-1.0, -1.0, 1.0, 0.0),
- (-1.0, 0.0, 0.0, 0.0),
- (-1.0, -1.0, 0.0, 1.0)]
-
- def _get_at_cursor_alignments(self, inv_rect=None):
- return [(0.0, 0.0, 1.0, 1.0),
- (0.0, -1.0, 1.0, 0.0),
- (-1.0, -1.0, 0.0, 0.0),
- (-1.0, 0.0, 0.0, 1.0)]
-
def _update_full_request(self):
state = self.palette_state
@@ -333,61 +268,35 @@ class Palette(gtk.Window):
self._set_state(state)
- def _update_cursor_position(self):
- display = gtk.gdk.display_get_default()
- screen, x, y, mask = display.get_pointer()
- self._cursor_x = x
- self._cursor_y = y
-
def _update_position(self):
- x = y = 0
-
- if self._position == self.DEFAULT:
- position = self._invoker.get_default_position()
- else:
- position = self._position
-
- inv_rect = None
- if position == self.AT_CURSOR:
- dist = style.PALETTE_CURSOR_DISTANCE
- inv_rect = gtk.gdk.Rectangle(self._cursor_x - dist,
- self._cursor_y - dist,
- dist * 2, dist * 2)
+ invoker = self._invoker
+ if invoker is None or self._alignment is None:
+ logging.error('Cannot update the palette position.')
+ return
- alignments = self._get_around_alignments()[:]
- if self._current_alignment is not None:
- alignments.remove(self._current_alignment)
- alignments.insert(0, self._current_alignment)
+ rect = self.size_request()
+ position = invoker.get_position_for_alignment(self._alignment, rect)
+ if position is None:
+ position = invoker.get_position(rect)
- for align in alignments:
- rect = self._get_rectangle(align, inv_rect=inv_rect)
- if self._in_screen(rect):
- break
-
- self.move(rect.x, rect.y)
+ self.move(position.x, position.y)
def _show(self):
if self._up:
return
- self._update_cursor_position()
- self._update_full_request()
-
self._palette_popup_sid = _palette_observer.connect(
'popup', self._palette_observer_popup_cb)
- for align in self._get_around_alignments():
- rect = self._get_rectangle(align, full=True)
- if self._in_screen(rect):
- self._current_alignment = align
- break
+ if self._invoker is not None:
+ self._update_full_request()
+ self._alignment = self._invoker.get_alignment(self._full_request)
+ self._update_position()
- self._update_position()
self.menu.set_active(True)
self.show()
- if self._invoker:
- self._invoker.notify_popup()
+ self._invoker.notify_popup()
self._up = True
_palette_observer.emit('popup', self)
@@ -541,28 +450,109 @@ class Invoker(gobject.GObject):
'focus-out': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([]))
}
+ ANCHORED = 0
+ AT_CURSOR = 1
+
+ BOTTOM = [(0.0, 0.0, 0.0, 1.0),
+ (-1.0, 0.0, 1.0, 1.0)]
+ RIGHT = [(0.0, 0.0, 1.0, 0.0),
+ (0.0, -1.0, 1.0, 1.0)]
+ TOP = [(0.0, -1.0, 0.0, 0.0),
+ (-1.0, -1.0, 1.0, 0.0)]
+ LEFT = [(-1.0, 0.0, 0.0, 0.0),
+ (-1.0, -1.0, 0.0, 1.0)]
+
def __init__(self):
gobject.GObject.__init__(self)
+ self._screen_area = gtk.gdk.Rectangle(0, 0, gtk.gdk.screen_width(),
+ gtk.gdk.screen_height())
+ self._alignments = self.BOTTOM + self.RIGHT + self.TOP + self.LEFT
+ self._position_hint = self.ANCHORED
+ self._cursor_x = -1
+ self._cursor_y = -1
+
+ def _get_position_for_alignment(self, alignment, palette_dim):
+ palette_halign = alignment[0]
+ palette_valign = alignment[1]
+ invoker_halign = alignment[2]
+ invoker_valign = alignment[3]
+
+ if self._cursor_x == -1 or self._cursor_y == -1:
+ display = gtk.gdk.display_get_default()
+ screen, x, y, mask = display.get_pointer()
+ self._cursor_x = x
+ self._cursor_y = y
+
+ if self._position_hint is self.ANCHORED:
+ rect = self.get_rect()
+ else:
+ dist = style.PALETTE_CURSOR_DISTANCE
+ rect = gtk.gdk.Rectangle(self._cursor_x - dist,
+ self._cursor_y - dist,
+ dist * 2, dist * 2)
+
+ palette_width, palette_height = palette_dim
+
+ x = rect.x + rect.width * invoker_halign + \
+ palette_width * palette_halign
+
+ y = rect.y + rect.height * invoker_valign + \
+ palette_height * palette_valign
+
+ return gtk.gdk.Rectangle(int(x), int(y),
+ palette_width, palette_height)
+
+ def _in_screen(self, rect):
+ return rect.x >= self._screen_area.x and \
+ rect.y >= self._screen_area.y and \
+ rect.x + rect.width <= self._screen_area.width and \
+ rect.y + rect.height <= self._screen_area.height
+
+ def _get_alignments(self):
+ if self._position_hint is self.AT_CURSOR:
+ return [(0.0, 0.0, 1.0, 1.0),
+ (0.0, -1.0, 1.0, 0.0),
+ (-1.0, -1.0, 0.0, 0.0),
+ (-1.0, 0.0, 0.0, 1.0)]
+ else:
+ return self._alignments
+
+ def get_position_for_alignment(self, alignment, palette_dim):
+ rect = self._get_position_for_alignment(alignment, palette_dim)
+ if self._in_screen(rect):
+ return rect
+ else:
+ return None
+
+ def get_position(self, palette_dim):
+ for alignment in self._get_alignments():
+ rect = self._get_position_for_alignment(alignment, palette_dim)
+ if self._in_screen(rect):
+ break
+
+ return rect
+
+ def get_alignment(self, palette_dim):
+ for alignment in self._get_alignments():
+ rect = self._get_position_for_alignment(alignment, palette_dim)
+ if self._in_screen(rect):
+ break
+
+ return alignment
+
def has_rectangle_gap(self):
return False
def draw_rectangle(self, event, palette):
pass
- def get_default_position(self):
- return Palette.AROUND
-
- def get_screen_area(self):
- width = gtk.gdk.screen_width()
- height = gtk.gdk.screen_height()
- return gtk.gdk.Rectangle(0, 0, width, height)
-
def notify_popup(self):
pass
def notify_popdown(self):
- pass
+ self._cursor_x = -1
+ self._cursor_y = -1
class WidgetInvoker(Invoker):
def __init__(self, widget):
@@ -617,15 +607,19 @@ class WidgetInvoker(Invoker):
return self._widget.get_toplevel()
def notify_popup(self):
+ Invoker.notify_popup(self)
self._widget.queue_draw()
def notify_popdown(self):
+ Invoker.notify_popdown(self)
self._widget.queue_draw()
class CanvasInvoker(Invoker):
def __init__(self, item):
Invoker.__init__(self)
+
self._item = item
+ self._position_hint = self.AT_CURSOR
item.connect('motion-notify-event',
self._motion_notify_event_cb)
@@ -644,6 +638,7 @@ class CanvasInvoker(Invoker):
def _motion_notify_event_cb(self, button, event):
if event.detail == hippo.MOTION_DETAIL_ENTER:
+ context = self._item.get_context()
self.emit('mouse-enter')
elif event.detail == hippo.MOTION_DETAIL_LEAVE:
self.emit('mouse-leave')