accerciser r593 - in trunk: . debian src/lib/accerciser



Author: eitani
Date: Tue Jul  8 18:46:09 2008
New Revision: 593
URL: http://svn.gnome.org/viewvc/accerciser?rev=593&view=rev

Log:
    * accerciser.schemas.in:
    * debian/changelog:
    * debian/rules:
    * src/lib/accerciser/accessible_treeview.py:
    * src/lib/accerciser/node.py:
    * src/lib/accerciser/prefs_dialog.py:
    * src/lib/accerciser/tools.py: Added new highlight features and
    eye-candy. Updated debian dirs.


Modified:
   trunk/ChangeLog
   trunk/accerciser.schemas.in
   trunk/debian/changelog
   trunk/debian/rules
   trunk/src/lib/accerciser/accessible_treeview.py
   trunk/src/lib/accerciser/node.py
   trunk/src/lib/accerciser/prefs_dialog.py
   trunk/src/lib/accerciser/tools.py

Modified: trunk/accerciser.schemas.in
==============================================================================
--- trunk/accerciser.schemas.in	(original)
+++ trunk/accerciser.schemas.in	Tue Jul  8 18:46:09 2008
@@ -33,5 +33,36 @@
         <long>A list of plugins that are disabled by default</long>
       </locale>
     </schema>
+    <schema>
+	  <key>/schemas/apps/accerciser/highlight_duration</key>
+	  <applyto>/apps/accerciser/highlight_duration</applyto>
+	  <type>float</type>
+	  <default>0.5</default>
+      <locale name="C">
+        <short>Highlight duration</short>
+        <long>The duration of the highlight box when selecting
+  accessible nodes</long>
+      </locale>
+    </schema>
+    <schema>
+	  <key>/schemas/apps/accerciser/highlight_border</key>
+	  <applyto>/apps/accerciser/highlight_border</applyto>
+	  <type>string</type>
+	  <default>0xff0000ff</default>
+      <locale name="C">
+        <short>Highlight border color</short>
+        <long>The color and opacity of the highlight border.</long>
+      </locale>
+    </schema>
+    <schema>
+	  <key>/schemas/apps/accerciser/highlight_fill</key>
+	  <applyto>/apps/accerciser/highlight_fill</applyto>
+	  <type>string</type>
+	  <default>0xff00006f</default>
+      <locale name="C">
+        <short>Highlight fill color</short>
+        <long>The color and opacity of the highlight fill.</long>
+      </locale>
+    </schema>
   </schemalist>
 </gconfschemafile>

Modified: trunk/debian/changelog
==============================================================================
--- trunk/debian/changelog	(original)
+++ trunk/debian/changelog	Tue Jul  8 18:46:09 2008
@@ -1,3 +1,9 @@
+accerciser (1.3.5) intrepid; urgency=low
+
+  * Test!
+
+ -- Eitan Isaacson <eitan ascender com>  Mon, 07 Jul 2008 17:12:56 -0700
+
 accerciser (1.1.92) gutsy; urgency=low
 
   * New dev release

Modified: trunk/debian/rules
==============================================================================
--- trunk/debian/rules	(original)
+++ trunk/debian/rules	Tue Jul  8 18:46:09 2008
@@ -79,7 +79,7 @@
 	dh_scrollkeeper
 	dh_desktop
 	dh_gconf
-	dh_iconcache
+	dh_icons
 	dh_pycentral
 	dh_installdeb
 	dh_gencontrol

Modified: trunk/src/lib/accerciser/accessible_treeview.py
==============================================================================
--- trunk/src/lib/accerciser/accessible_treeview.py	(original)
+++ trunk/src/lib/accerciser/accessible_treeview.py	Tue Jul  8 18:46:09 2008
@@ -798,4 +798,4 @@
     @param view_column: The column in the activated row.
     @type view_column: L{gtk.TreeViewColumn}
     '''
-    self.node.blinkRect()
+    self.node.highlight()

Modified: trunk/src/lib/accerciser/node.py
==============================================================================
--- trunk/src/lib/accerciser/node.py	(original)
+++ trunk/src/lib/accerciser/node.py	Tue Jul  8 18:46:09 2008
@@ -15,10 +15,23 @@
 import gtk.gdk
 import pyatspi
 import gobject
-from tools import Tools
+import string
+import rsvg
+import cairo
+from tools import Tools, parseColorString
+import gconf
 
 MAX_BLINKS = 6
 
+cl = gconf.client_get_default()
+BORDER_COLOR, BORDER_ALPHA = parseColorString(
+  cl.get_string('/apps/accerciser/highlight_border'))
+
+FILL_COLOR, FILL_ALPHA  = parseColorString(
+  cl.get_string('/apps/accerciser/highlight_fill'))
+
+HL_DURATION = int(cl.get_float('/apps/accerciser/highlight_duration')*1000)
+
 class Bag(object):
   '''
   Bag class for converting a dicionary to an object with attributes.
@@ -79,7 +92,7 @@
       if isinstance(i, pyatspi.Accessibility.Component):
         self.extents = i.getExtents(pyatspi.DESKTOP_COORDS)
     self.tree_path = None
-    self.blinkRect()
+    self.highlight()
     self.emit('accessible-changed', acc)
   
   def updateToPath(self, app_name, path):
@@ -105,6 +118,17 @@
         return
     self.update(acc)
 
+  def highlight(self):
+    if self.extents is None or \
+          0 in (self.extents.width, self.extents.height) or \
+          -0x80000000 in (self.extents.x, self.extents.y):
+      return
+    ah = _HighLight(self.extents.x, self.extents.y, 
+                    self.extents.width, self.extents.height, 
+                    FILL_COLOR, FILL_ALPHA, BORDER_COLOR, BORDER_ALPHA, 
+                    2.0, 0)
+    ah.highlight(HL_DURATION)
+
   def blinkRect(self, times=MAX_BLINKS):
     '''
     Blink a rectangle on the screen using L{extents} for position and size.
@@ -151,3 +175,99 @@
       return False
     return True
 
+class _HighLight(gtk.Window):
+  '''
+  Highlight box class. Uses compositing when available. When not, it does
+  transparency client-side.
+  '''
+  _svg = r"""
+<svg width="100%" height="100%" version="1.1"
+  xmlns="http://www.w3.org/2000/svg";>
+  <rect x="$x" y="$y" width="$width" height="$height"
+      style="fill:$fill;stroke-width:$stroke_width;stroke:$stroke;
+      fill-opacity:$fill_opacity;stroke-opacity:$stroke_opacity"
+      rx="2" ry="2"
+      />
+</svg>
+"""
+  def __init__(self, x, y, w, h, 
+               fill_color, fill_alpha,
+               stroke_color, stroke_alpha, 
+               stroke_width, padding=0):
+
+    # Initialize window.
+    gtk.Window.__init__(self, gtk.WINDOW_POPUP)
+
+    # Normalize position for stroke and padding.
+    self.x, self.y = x - padding, y - padding
+    self.w, self.h = w + padding*2, h + padding*2
+
+    # Determine if we are compositing.
+    self._composited = self.is_composited()
+    if False:
+      # Prepare window for transparency.
+      screen = self.get_screen()
+      colormap = screen.get_rgba_colormap()
+      self.set_colormap(colormap)
+    else:
+      # Take a screenshot for compositing on the client side.
+      self.root = gtk.gdk.get_default_root_window().get_image(
+        self.x, self.y, self.w, self.h)
+
+    # Place window, and resize it, and set proper properties.
+    self.set_app_paintable(True)
+    self.set_decorated(False)
+    self.set_keep_above(True)
+    self.move(self.x, self.y)
+    self.resize(self.w, self.h)
+    self.set_accept_focus(False)
+    self.set_sensitive(False)
+
+    # Create SVG with given parameters.
+    offset = stroke_width/2.0
+    self.svg = string.Template(self._svg).substitute(
+      x=offset, y=offset,
+      width=int(self.w - stroke_width), height=int(self.h - stroke_width),
+      fill=fill_color, 
+      stroke_width=stroke_width,
+      stroke=stroke_color,
+      fill_opacity=fill_alpha,
+      stroke_opacity=stroke_alpha)
+
+    # Connect "expose" event.
+    self.connect("expose-event", self._onExpose)
+    
+  def highlight(self, duration=0):
+    if duration > 0:
+      gobject.timeout_add(duration, lambda w: w.destroy(), self)
+    self.show_all()
+    
+
+  def _onExpose(self, widget, event):
+    svgh = rsvg.Handle()
+    try:
+      svgh.write(self.svg)
+    except (gobject.GError, KeyError, ValueError), ex:
+      print 'Error reading SVG for display: %s\r\n%s', ex, self.svg
+      svgh.close()
+      return
+    finally:
+      svgh.close()
+      
+    if not self._composited:
+      # Draw the screengrab of the underlaying window, and set the drawing
+      # operator to OVER.
+      self.window.draw_image(self.style.black_gc, self.root, 
+                             event.area.x,event.area.y, 
+                             event.area.x, event.area.y, 
+                             event.area.width, event.area.height)
+      cairo_operator = cairo.OPERATOR_OVER
+    else:
+      cairo_operator = cairo.OPERATOR_SOURCE
+    cr = self.window.cairo_create()
+    cr.set_source_rgba(1.0, 1.0, 1.0, 0.0)
+    cr.set_operator(cairo_operator)
+    cr.paint()
+
+    svgh.render_cairo( cr )
+    del svgh

Modified: trunk/src/lib/accerciser/prefs_dialog.py
==============================================================================
--- trunk/src/lib/accerciser/prefs_dialog.py	(original)
+++ trunk/src/lib/accerciser/prefs_dialog.py	Tue Jul  8 18:46:09 2008
@@ -13,6 +13,10 @@
 
 import gtk
 from i18n import _
+import atk
+import gconf
+import node
+from tools import parseColorString
 
 class AccerciserPreferencesDialog(gtk.Dialog):
   '''
@@ -41,6 +45,8 @@
         sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
         sw.add(view)
         notebook.append_page(sw, gtk.Label(section))
+    
+    notebook.append_page(_HighlighterView(), gtk.Label(_('Highlighting')))
         
   def _onResponse(self, dialog, response_id):
     '''
@@ -52,3 +58,130 @@
     @type response_id: integer
     '''
     dialog.destroy()
+
+class _HighlighterView(gtk.Alignment):
+  '''
+  A container widget with the settings for the highlighter.
+  '''
+  def __init__(self):
+    gtk.Alignment.__init__(self)
+    self.set_padding(0, 0, 20, 0)
+    self.gconf_cl = gconf.client_get_default()
+    self._buildUI()
+
+  def _buildUI(self):
+    '''
+    Programatically build the UI.
+    '''
+    table = gtk.Table(3, 2)
+    table.set_col_spacings(6)
+    self.add(table)
+    labels = [None, None, None]
+    controls = [None, None, None]
+    labels[0] = gtk.Label(_('Highlight duration:'))
+    controls[0] = gtk.SpinButton()
+    controls[0].set_range(0.01, 5)
+    controls[0].set_digits(2)
+    controls[0].set_value(
+      self.gconf_cl.get_float('/apps/accerciser/highlight_duration'))
+    controls[0].set_increments(0.01, 0.1)
+    controls[0].connect('value-changed', self._onDurationChanged)
+    labels[1] = gtk.Label(_('Border color:'))
+    controls[1] = self._ColorButton(
+      self.gconf_cl.get_string('/apps/accerciser/highlight_border'))
+    controls[1].connect('color-set', self._onColorSet, 'highlight_border')
+    controls[1].set_tooltip_text(_('The border color of the highlight box'))
+    labels[2] = gtk.Label(_('Fill color:'))
+    controls[2] = self._ColorButton(
+      self.gconf_cl.get_string('/apps/accerciser/highlight_fill'))
+    controls[2].connect('color-set', self._onColorSet, 'highlight_fill')
+    controls[2].set_tooltip_text(_('The fill color of the highlight box'))
+
+    for label, control, row in zip(labels, controls, range(3)):
+      label.set_alignment(0, 0.5)
+      table.attach(label, 0, 1, row, row + 1, gtk.FILL)
+      table.attach(control, 1, 2, row, row + 1, gtk.FILL)
+
+    for label, control in zip(map(lambda x: x.get_accessible(),labels),
+                              map(lambda x: x.get_accessible(),controls)):
+      label.add_relationship(atk.RELATION_LABEL_FOR, control)
+      control.add_relationship(atk.RELATION_LABELLED_BY, label)
+
+  def _onDurationChanged(self, spin_button):
+    '''
+    Callback for the duration spin button. Update gconf and the global variable
+    in the L{node} module.
+
+    @param spin_button: The spin button that emitted the value-changed signal.
+    @type spin_button: gtk.SpinButton
+    '''
+    node.HL_DURATION = int(spin_button.get_value()*1000)
+    self.gconf_cl.set_float('/apps/accerciser/highlight_duration',
+                            spin_button.get_value())
+                            
+
+  def _onColorSet(self, color_button, gconf_key):
+    '''
+    Callback for a color button. Update gconf and the global variables
+    in the L{node} module.
+
+    @param color_button: The color button that emitted the color-set signal.
+    @type color_button: l{_HighlighterView._ColorButton}
+    @param gconf_key: the key name suffix for this color setting.
+    @type gconf_key: string
+    '''
+    if 'fill' in gconf_key:
+      node.FILL_COLOR = color_button.get_rgb_string()
+      node.FILL_ALPHA = color_button.get_alpha_float()
+    else:
+      node.BORDER_COLOR = color_button.get_rgb_string()
+      node.BORDER_ALPHA = color_button.get_alpha_float()
+      
+    self.gconf_cl.set_string('/apps/accerciser/' + gconf_key,
+                             color_button.get_rgba_string())
+
+  class _ColorButton(gtk.ColorButton):
+    '''
+    ColorButton derivative with useful methods for us.
+    '''
+    def __init__(self, color_string):
+      gtk.ColorButton.__init__(self, gtk.gdk.color_parse(color_string[:-2]))
+      self.set_use_alpha(True)
+      self.set_alpha(int(color_string[-2:], 16) << 8)
+                               
+    def get_rgba_string(self):
+      '''
+      Get the current color and alpha in string format.
+
+      @return: String in the format of #rrggbbaa.
+      @rtype: string.
+      '''
+      color = self.get_color()
+      color_val = 0
+      color_val |= color.red >> 8 << 24
+      color_val |= color.green >> 8 << 16
+      color_val |= color.blue >> 8 << 8
+      color_val |= self.get_alpha() >> 8
+      return \
+          '#' + hex(color_val).replace('0x', '').replace('L', '').rjust(8, '0')
+
+    def get_rgb_string(self):
+      '''
+      Get the current color in string format.
+
+      @return: String in the format of #rrggbb.
+      @rtype: string.
+      '''
+      color = self.get_color()
+      color_val = 0
+      color_val |= color.red >> 8 << 16
+      color_val |= color.green >> 8 << 8
+      color_val |= color.blue >> 8
+      return \
+          '#' + hex(color_val).replace('0x', '').replace('L', '').rjust(6, '0')
+      
+    def get_alpha_float(self):
+      '''
+      Get the current alpha as a value from 0.0 to 1.0.
+      '''
+      return self.get_alpha()/float(0xffff)

Modified: trunk/src/lib/accerciser/tools.py
==============================================================================
--- trunk/src/lib/accerciser/tools.py	(original)
+++ trunk/src/lib/accerciser/tools.py	Tue Jul  8 18:46:09 2008
@@ -170,6 +170,19 @@
     '''
     return not self.__eq__(other)
 
+def parseColorString(color_string):
+  '''
+  Parse a string representation of a 24-bit color, and a 8 bit alpha mask.
+
+  @param color_string: String in the format: #rrbbggaa.
+  @type color_string: string
+
+  @return: A color string in the format of #rrggbb, and an opacity value 
+  of 0.0 to 1.0
+  @rtype: tuple of string and float.
+  '''
+  return color_string[:-2], long(color_string[-2:], 16)/255.0
+
 def getTreePathBoundingBox(treeview, path, col):
   '''
   Get bounding box of given tree path.
@@ -186,4 +199,3 @@
   rect.x += x
   rect.y += y
   return rect
-



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]