home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / python-support / gnome-orca / orca / outline.py < prev    next >
Encoding:
Python Source  |  2009-04-13  |  8.9 KB  |  265 lines

  1. #
  2. # Copyright 2008 Sun Microsystems Inc.
  3. #
  4. # This library is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU Library General Public
  6. # License as published by the Free Software Foundation; either
  7. # version 2 of the License, or (at your option) any later version.
  8. #
  9. # This library is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. # Library General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU Library General Public
  15. # License along with this library; if not, write to the
  16. # Free Software Foundation, Inc., Franklin Street, Fifth Floor,
  17. # Boston MA  02110-1301 USA.
  18.  
  19. """Provides a simple utility to draw outlines on the screen.
  20. [[[TODO: WDW - The Wedge support is experimental and not perfect.]]]"""
  21.  
  22. __id__        = "$Id: outline.py 4221 2008-09-15 08:11:23Z wwalker $"
  23. __version__   = "$Revision: 4221 $"
  24. __date__      = "$Date: 2008-09-15 04:11:23 -0400 (Mon, 15 Sep 2008) $"
  25. __copyright__ = "Copyright (c) 2008 Sun Microsystems Inc."
  26. __license__   = "LGPL"
  27.  
  28. import cairo
  29.  
  30. try:
  31.     # This can fail due to gtk not being available.  We want to
  32.     # be able to recover from that if possible.  The main driver
  33.     # for this is to allow "orca --text-setup" to work even if
  34.     # the desktop is not running.
  35.     #
  36.     import gtk
  37.     display = gtk.gdk.display_get_default()
  38.     screen = display.get_default_screen()
  39.     screen_width = screen.get_width()
  40.     screen_height = screen.get_height()
  41. except:
  42.     pass
  43.  
  44. import orca_state
  45. import settings
  46.  
  47. def _adjustToScreen(x, y, width, height):
  48.     if x < 0:
  49.         width = width + x
  50.         x = 0
  51.     elif x >= screen_width:
  52.         width -= (x - screen_width)
  53.         x = screen_width
  54.     if y < 0:
  55.         height = height + y
  56.         y = 0
  57.     elif y >= screen_height:
  58.         height -= (y - screen_height)
  59.         y = screen_height
  60.     if (x + width) >= screen_width:
  61.         width = screen_width - x
  62.     if (y + height) >= screen_height:
  63.         height = max(1, screen_height - y)
  64.     width = max(1, width)
  65.     height = max(1, height)
  66.     return [x, y, width, height]
  67.  
  68. # Our known windows that we've put on the screen.
  69. #
  70. _outlineWindows = []
  71.  
  72. class Line(gtk.Window):
  73.     """Draws a simple filled box on the display using
  74.     settings.outlineColor for the color.
  75.  
  76.     Arguments:
  77.     - x, y, width, height: the dimensions of the box
  78.     """
  79.     def __init__(self, x, y, width, height):
  80.         gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
  81.  
  82.         self.modify_bg(gtk.STATE_NORMAL,
  83.                        gtk.gdk.Color(settings.outlineColor[0],
  84.                                      settings.outlineColor[1],
  85.                                      settings.outlineColor[2]))
  86.  
  87.         self.set_property("accept-focus", False)
  88.         self.set_decorated(False)
  89.         self.set_keep_above(True)
  90.         self.set_skip_taskbar_hint(True)
  91.  
  92.         self.move(x, y)
  93.         self.set_default_size(width, height)
  94.         self.resize(width, height)
  95.         self.realize()
  96.  
  97. class Wedge(Line):
  98.     """Draws a filled isosceles triangle on the display
  99.     using settings.outlineColor for the color.
  100.  
  101.     Arguments:
  102.     - x, y, width, height - the bounding box of the triangle
  103.     - top - if true, the triangle is flat on the bottom,
  104.             if false, the triangle is pointy on the bottom
  105.     """
  106.     def __init__(self, x, y, width, height, top):
  107.         self.top = top
  108.         Line.__init__(self, x, y, width, height)
  109.         self.connect('size-allocate', self._on_size_allocate)
  110.  
  111.     def _on_size_allocate(self, win, allocation):
  112.         """Sets the shape of the window to a triangle."""
  113.         # Create a bitmap to draw into.  This will be the mask
  114.         # for the shape of the window.
  115.         #
  116.         width, height = allocation.width, allocation.height
  117.         bitmap = gtk.gdk.Pixmap(None, width, height, 1)
  118.         cr = bitmap.cairo_create()
  119.  
  120.         # Clear the bitmap
  121.         #
  122.         cr.set_source_rgb(0, 0, 0)
  123.         cr.set_operator(cairo.OPERATOR_DEST_OUT)
  124.         cr.paint()
  125.  
  126.         # Draw our shape into the bitmap using cairo
  127.         #
  128.         cr.set_operator(cairo.OPERATOR_OVER)
  129.         if self.top:
  130.             # In this case, height is the same as thickness
  131.             #
  132.             cr.move_to(width/2.0, 0.0)
  133.             cr.line_to(width/2.0 + height/2.0, height)
  134.             cr.line_to(width/2.0 - height/2.0, height)
  135.         else:
  136.             cr.move_to(width/2.0, height)
  137.             cr.line_to(width/2.0 + height/2.0, 0.0)
  138.             cr.line_to(width/2.0 - height/2.0, 0.0)
  139.         cr.close_path()
  140.         cr.fill()
  141.  
  142.         # Set the window shape
  143.         #
  144.         win.shape_combine_mask(bitmap, 0, 0)
  145.  
  146. class Box(Line):
  147.     """Draws the outline of a rectangle on the display
  148.     using settings.outlineColor for the color.
  149.  
  150.     Arguments:
  151.     - x, y, width, height - the bounding box of the rectangle
  152.     - thickness - the thickness of the border
  153.     """
  154.     def __init__(self, x, y, width, height, thickness):
  155.         self.thickness = thickness
  156.         Line.__init__(self, x, y, width, height)
  157.         self.connect('size-allocate', self._on_size_allocate)
  158.  
  159.     def _on_size_allocate(self, win, allocation):
  160.         """Sets the shape of the window to a hollow rectangle."""
  161.         # Create a bitmap to draw into.  This will be the mask
  162.         # for the shape of the window.
  163.         #
  164.         width, height = allocation.width, allocation.height
  165.         bitmap = gtk.gdk.Pixmap(None, width, height, 1)
  166.         cr = bitmap.cairo_create()
  167.  
  168.         # Clear the bitmap
  169.         #
  170.         cr.set_source_rgb(0, 0, 0)
  171.         cr.set_operator(cairo.OPERATOR_DEST_OUT)
  172.         cr.paint()
  173.  
  174.         # Draw our shape into the bitmap using cairo
  175.         #
  176.         cr.set_line_width(self.thickness)
  177.         cr.set_operator(cairo.OPERATOR_OVER)
  178.         offset = self.thickness / 2.0
  179.         cr.rectangle(0.0 + offset, 0.0 + offset,
  180.                      width - self.thickness, height - self.thickness)
  181.         cr.stroke()
  182.  
  183.         # Set the window shape
  184.         #
  185.         win.shape_combine_mask(bitmap, 0, 0)
  186.  
  187. def reset():
  188.     """Destroys all windows we have put on the screen."""
  189.     global _outlineWindows
  190.     for window in _outlineWindows:
  191.         window.destroy()
  192.     _outlineWindows = []
  193.    
  194. def erase():
  195.     """Erases all windows we have put on the screen."""
  196.     for window in _outlineWindows:
  197.         window.hide()
  198.  
  199. def draw(x, y, width, height):
  200.     """Draws an outline for the given rectangle.  This might
  201.     be composed of multiple windows depending upon the
  202.     settings.outlineStyle."""
  203.  
  204.     if settings.outlineStyle == settings.OUTLINE_NONE:
  205.         pass
  206.     elif settings.outlineStyle == settings.OUTLINE_LINE:
  207.         y = y + height + settings.outlineMargin
  208.         height = settings.outlineThickness
  209.         [x, y, width, height] = _adjustToScreen(x, y, width, height)
  210.         if not _outlineWindows:
  211.             line = \
  212.                 Line(x, y, width, height)
  213.             _outlineWindows.append(line)
  214.         else:
  215.             _outlineWindows[0].resize(width, height)
  216.             _outlineWindows[0].move(x, y)
  217.     elif settings.outlineStyle == settings.OUTLINE_BOX:
  218.         extra = settings.outlineThickness + settings.outlineMargin
  219.         x = x - extra
  220.         y = y - extra
  221.         width = width + (2 * extra)
  222.         height = height + (2 * extra)
  223.         [x, y, width, height] = _adjustToScreen(x, y, width, height)
  224.         if not _outlineWindows:
  225.             box = \
  226.                 Box(x, y, width, height,
  227.                     settings.outlineThickness)
  228.             _outlineWindows.append(box)
  229.         else:
  230.             _outlineWindows[0].resize(width, height)
  231.             _outlineWindows[0].move(x, y)
  232.     elif settings.outlineStyle == settings.OUTLINE_WEDGES:
  233.         wedgeSize = 4 * settings.outlineThickness
  234.         if width < wedgeSize:
  235.             diff = wedgeSize - width
  236.             width = wedgeSize
  237.             x -= (diff/2)
  238.         topy = y - (4 * settings.outlineThickness)
  239.         bottomy = y + height + settings.outlineMargin
  240.         [topx, topy, topwidth, topheight] = \
  241.            _adjustToScreen(x, topy, width, wedgeSize)
  242.         [bottomx, bottomy, bottomwidth, bottomheight] = \
  243.            _adjustToScreen(x, bottomy, width, wedgeSize)
  244.         if not _outlineWindows:
  245.             top = \
  246.                 Wedge(topx, topy, topwidth, topheight, True)
  247.             _outlineWindows.append(top)
  248.             bottom = \
  249.                 Wedge(bottomx, bottomy, bottomwidth, bottomheight, False)
  250.             _outlineWindows.append(bottom)
  251.         else:
  252.             _outlineWindows[0].resize(topwidth, topheight)
  253.             _outlineWindows[0].move(topx, topy)
  254.             _outlineWindows[1].resize(bottomwidth, bottomheight)
  255.             _outlineWindows[1].move(bottomx, bottomy)
  256.  
  257.     for window in _outlineWindows:
  258.         window.present()
  259.         # Make sure the windows stay on top.
  260.         #
  261.         try:
  262.             window.window.set_user_time(orca_state.lastInputEventTimestamp)
  263.         except:
  264.             pass
  265.