Revision: 6372
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6372&view=rev
Author:   mdboom
Date:     2008-11-07 14:52:04 +0000 (Fri, 07 Nov 2008)

Log Message:
-----------
Committed Andrew Straw's patch to support hyperlinks.  Currently only the SVG 
backend, but the infrastructure is there for other backends to support it.

Modified Paths:
--------------
    trunk/matplotlib/lib/matplotlib/artist.py
    trunk/matplotlib/lib/matplotlib/axes.py
    trunk/matplotlib/lib/matplotlib/backend_bases.py
    trunk/matplotlib/lib/matplotlib/backends/backend_ps.py
    trunk/matplotlib/lib/matplotlib/backends/backend_svg.py
    trunk/matplotlib/lib/matplotlib/collections.py
    trunk/matplotlib/lib/matplotlib/image.py
    trunk/matplotlib/lib/matplotlib/patches.py
    trunk/matplotlib/lib/matplotlib/text.py
    trunk/matplotlib/src/_backend_agg.cpp

Added Paths:
-----------
    trunk/matplotlib/examples/pylab_examples/hyperlinks.py

Added: trunk/matplotlib/examples/pylab_examples/hyperlinks.py
===================================================================
--- trunk/matplotlib/examples/pylab_examples/hyperlinks.py                      
        (rev 0)
+++ trunk/matplotlib/examples/pylab_examples/hyperlinks.py      2008-11-07 
14:52:04 UTC (rev 6372)
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+# -*- noplot -*-
+
+"""
+This example demonstrates how to set a hyperlinks on various kinds of elements.
+
+This currently only works with the SVG backend.
+"""
+
+import numpy as np
+import matplotlib.cm as cm
+import matplotlib.mlab as mlab
+import matplotlib.pyplot as plt
+
+f = plt.figure()
+s = plt.scatter([1,2,3],[4,5,6])
+s.set_urls(['http://www.bbc.co.uk/news','http://www.google.com',None])
+f.canvas.print_figure('scatter.svg')
+
+f = plt.figure()
+delta = 0.025
+x = y = np.arange(-3.0, 3.0, delta)
+X, Y = np.meshgrid(x, y)
+Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
+Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
+Z = Z2-Z1  # difference of Gaussians
+
+im = plt.imshow(Z, interpolation='bilinear', cmap=cm.gray,
+                origin='lower', extent=[-3,3,-3,3])
+
+im.set_url('http://www.google.com')
+f.canvas.print_figure('image.svg')
+

Modified: trunk/matplotlib/lib/matplotlib/artist.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/artist.py   2008-11-07 13:31:25 UTC (rev 
6371)
+++ trunk/matplotlib/lib/matplotlib/artist.py   2008-11-07 14:52:04 UTC (rev 
6372)
@@ -50,6 +50,7 @@
         self._propobservers = {} # a dict from oids to funcs
         self.axes = None
         self._remove_method = None
+        self._url = None
 
     def remove(self):
         """
@@ -313,6 +314,18 @@
         """
         return self.figure is not None
 
+    def get_url(self):
+        """
+        Returns the url
+        """
+        return self._url
+    
+    def set_url(self, url):
+        """
+        Sets the url for the artist
+        """
+        self._url = url
+
     def get_figure(self):
         """
         Return the :class:`~matplotlib.figure.Figure` instance the

Modified: trunk/matplotlib/lib/matplotlib/axes.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/axes.py     2008-11-07 13:31:25 UTC (rev 
6371)
+++ trunk/matplotlib/lib/matplotlib/axes.py     2008-11-07 14:52:04 UTC (rev 
6372)
@@ -5480,7 +5480,7 @@
     def imshow(self, X, cmap=None, norm=None, aspect=None,
                interpolation=None, alpha=1.0, vmin=None, vmax=None,
                origin=None, extent=None, shape=None, filternorm=1,
-               filterrad=4.0, imlim=None, resample=None, **kwargs):
+               filterrad=4.0, imlim=None, resample=None, url=None, **kwargs):
         """
         call signature::
 
@@ -5601,6 +5601,7 @@
             im.set_clim(vmin, vmax)
         else:
             im.autoscale_None()
+        im.set_url(url)
 
         xmin, xmax, ymin, ymax = im.get_extent()
 

Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backend_bases.py    2008-11-07 13:31:25 UTC 
(rev 6371)
+++ trunk/matplotlib/lib/matplotlib/backend_bases.py    2008-11-07 14:52:04 UTC 
(rev 6372)
@@ -107,7 +107,7 @@
     def draw_path_collection(self, master_transform, cliprect, clippath,
                              clippath_trans, paths, all_transforms, offsets,
                              offsetTrans, facecolors, edgecolors, linewidths,
-                             linestyles, antialiaseds):
+                             linestyles, antialiaseds, urls):
         """
         Draws a collection of paths, selecting drawing properties from
         the lists *facecolors*, *edgecolors*, *linewidths*,
@@ -136,7 +136,7 @@
         for xo, yo, path_id, gc, rgbFace in self._iter_collection(
             path_ids, cliprect, clippath, clippath_trans,
             offsets, offsetTrans, facecolors, edgecolors,
-            linewidths, linestyles, antialiaseds):
+            linewidths, linestyles, antialiaseds, urls):
             path, transform = path_id
             transform = 
transforms.Affine2D(transform.get_matrix()).translate(xo, yo)
             self.draw_path(gc, path, transform, rgbFace)
@@ -164,7 +164,7 @@
         return self.draw_path_collection(
             master_transform, cliprect, clippath, clippath_trans,
             paths, [], offsets, offsetTrans, facecolors, edgecolors,
-            linewidths, [], [antialiased])
+            linewidths, [], [antialiased], [None])
 
     def _iter_collection_raw_paths(self, master_transform, paths, 
all_transforms):
         """
@@ -198,7 +198,7 @@
 
     def _iter_collection(self, path_ids, cliprect, clippath, clippath_trans,
                          offsets, offsetTrans, facecolors, edgecolors,
-                         linewidths, linestyles, antialiaseds):
+                         linewidths, linestyles, antialiaseds, urls):
         """
         This is a helper method (along with
         :meth:`_iter_collection_raw_paths`) to make it easier to write
@@ -232,6 +232,7 @@
         Nlinewidths = len(linewidths)
         Nlinestyles = len(linestyles)
         Naa         = len(antialiaseds)
+        Nurls       = len(urls)
 
         if (Nfacecolors == 0 and Nedgecolors == 0) or Npaths == 0:
             return
@@ -268,6 +269,9 @@
                 gc.set_alpha(rgbFace[-1])
                 rgbFace = rgbFace[:3]
             gc.set_antialiased(antialiaseds[i % Naa])
+            
+            if Nurls:
+                gc.set_url(urls[i % Nurls])
 
             yield xo, yo, path_id, gc, rgbFace
 
@@ -433,6 +437,7 @@
         self._linewidth = 1
         self._rgb = (0.0, 0.0, 0.0)
         self._hatch = None
+        self._url = None
 
     def copy_properties(self, gc):
         'Copy properties from gc to self'
@@ -447,6 +452,7 @@
         self._linewidth = gc._linewidth
         self._rgb = gc._rgb
         self._hatch = gc._hatch
+        self._url = gc._url
 
     def get_alpha(self):
         """
@@ -521,6 +527,12 @@
         matlab format string, a html hex color string, or a rgb tuple
         """
         return self._rgb
+    
+    def get_url(self):
+        """
+        returns a url if one is set, None otherwise
+        """
+        return self._url
 
     def set_alpha(self, alpha):
         """
@@ -621,6 +633,12 @@
             raise ValueError('Unrecognized linestyle: %s' % style)
         self._linestyle = style
         self.set_dashes(offset, dashes)
+        
+    def set_url(self, url):
+        """
+        Sets the url for links in compatible backends
+        """
+        self._url = url
 
     def set_hatch(self, hatch):
         """

Modified: trunk/matplotlib/lib/matplotlib/backends/backend_ps.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_ps.py      2008-11-07 
13:31:25 UTC (rev 6371)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_ps.py      2008-11-07 
14:52:04 UTC (rev 6372)
@@ -531,7 +531,7 @@
     def draw_path_collection(self, master_transform, cliprect, clippath,
                              clippath_trans, paths, all_transforms, offsets,
                              offsetTrans, facecolors, edgecolors, linewidths,
-                             linestyles, antialiaseds):
+                             linestyles, antialiaseds, urls):
         write = self._pswriter.write
 
         path_codes = []
@@ -548,7 +548,7 @@
         for xo, yo, path_id, gc, rgbFace in self._iter_collection(
             path_codes, cliprect, clippath, clippath_trans,
             offsets, offsetTrans, facecolors, edgecolors,
-            linewidths, linestyles, antialiaseds):
+            linewidths, linestyles, antialiaseds, urls):
 
             ps = "%g %g %s" % (xo, yo, path_id)
             self._draw_ps(ps, gc, rgbFace)

Modified: trunk/matplotlib/lib/matplotlib/backends/backend_svg.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_svg.py     2008-11-07 
13:31:25 UTC (rev 6371)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_svg.py     2008-11-07 
14:52:04 UTC (rev 6372)
@@ -67,9 +67,13 @@
         else:
             clippath = 'clip-path="url(#%s)"' % clipid
 
+        if gc.get_url() is not None:
+            self._svgwriter.write('<a xlink:href="%s">' % gc.get_url())
         style = self._get_style(gc, rgbFace)
         self._svgwriter.write ('<%s style="%s" %s %s/>\n' % (
                 element, style, clippath, details))
+        if gc.get_url() is not None:
+            self._svgwriter.write('</a>')
 
     def _get_font(self, prop):
         key = hash(prop)
@@ -224,7 +228,7 @@
     def draw_path_collection(self, master_transform, cliprect, clippath,
                              clippath_trans, paths, all_transforms, offsets,
                              offsetTrans, facecolors, edgecolors, linewidths,
-                             linestyles, antialiaseds):
+                             linestyles, antialiaseds, urls):
         write = self._svgwriter.write
 
         path_codes = []
@@ -242,8 +246,11 @@
         for xo, yo, path_id, gc, rgbFace in self._iter_collection(
             path_codes, cliprect, clippath, clippath_trans,
             offsets, offsetTrans, facecolors, edgecolors,
-            linewidths, linestyles, antialiaseds):
+            linewidths, linestyles, antialiaseds, urls):
             clipid = self._get_gc_clip_svg(gc)
+            url = gc.get_url()
+            if url is not None:
+                self._svgwriter.write('<a xlink:href="%s">' % url)
             if clipid is not None:
                 write('<g clip-path="url(#%s)">' % clipid)
             details = 'xlink:href="#%s" x="%f" y="%f"' % (path_id, xo, 
self.height - yo)
@@ -251,6 +258,8 @@
             self._svgwriter.write ('<use style="%s" %s/>\n' % (style, details))
             if clipid is not None:
                 write('</g>')
+            if url is not None:
+                self._svgwriter.write('</a>')
 
         self._path_collection_id += 1
 
@@ -274,6 +283,9 @@
 
         h,w = im.get_size_out()
 
+        url = getattr(im, '_url', None)
+        if url is not None:
+            self._svgwriter.write('<a xlink:href="%s">' % url)
         self._svgwriter.write (
             '<image x="%f" y="%f" width="%f" height="%f" '
             '%s xlink:href="'%(x/trans[0], (self.height-y)/trans[3]-h, w, h, 
transstr)
@@ -298,6 +310,8 @@
             self._svgwriter.write(filename)
 
         self._svgwriter.write('"/>\n')
+        if url is not None:
+            self._svgwriter.write('</a>')
 
     def draw_text(self, gc, x, y, s, prop, angle, ismath):
         if ismath:

Modified: trunk/matplotlib/lib/matplotlib/collections.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/collections.py      2008-11-07 13:31:25 UTC 
(rev 6371)
+++ trunk/matplotlib/lib/matplotlib/collections.py      2008-11-07 14:52:04 UTC 
(rev 6372)
@@ -71,6 +71,7 @@
                  norm = None,  # optional for ScalarMappable
                  cmap = None,  # ditto
                  pickradius = 5.0,
+                 urls = None,
                  **kwargs
                  ):
         """
@@ -86,6 +87,7 @@
         self.set_linewidth(linewidths)
         self.set_linestyle(linestyles)
         self.set_antialiased(antialiaseds)
+        self.set_urls(urls)
 
         self._uniform_offsets = None
         self._offsets = np.array([], np.float_)
@@ -203,7 +205,7 @@
             paths, self.get_transforms(),
             offsets, transOffset,
             self.get_facecolor(), self.get_edgecolor(), self._linewidths,
-            self._linestyles, self._antialiaseds)
+            self._linestyles, self._antialiaseds, self._urls)
         renderer.close_group(self.__class__.__name__)
 
     def contains(self, mouseevent):
@@ -227,6 +229,14 @@
     def set_pickradius(self,pickradius): self.pickradius = 5
     def get_pickradius(self): return self.pickradius
 
+    def set_urls(self, urls):
+       if urls is None:
+            self._urls = [None,]
+        else:
+            self._urls = urls
+        
+    def get_urls(self): return self._urls
+
     def set_offsets(self, offsets):
         """
         Set the offsets for the collection.  *offsets* can be a scalar

Modified: trunk/matplotlib/lib/matplotlib/image.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/image.py    2008-11-07 13:31:25 UTC (rev 
6371)
+++ trunk/matplotlib/lib/matplotlib/image.py    2008-11-07 14:52:04 UTC (rev 
6372)
@@ -88,13 +88,10 @@
         self.set_filterrad(filterrad)
         self._filterrad = filterrad
 
-
-
         self.set_interpolation(interpolation)
         self.set_resample(resample)
         self.axes = ax
 
-
         self._imcache = None
 
         self.update(kwargs)
@@ -234,9 +231,11 @@
             self.axes.get_yscale() != 'linear'):
             warnings.warn("Images are not supported on non-linear axes.")
         im = self.make_image(renderer.get_image_magnification())
+        im._url = self.get_url()
         l, b, widthDisplay, heightDisplay = self.axes.bbox.bounds
+        clippath, affine = self.get_transformed_clip_path_and_affine()
         renderer.draw_image(round(l), round(b), im, self.axes.bbox.frozen(),
-                            *self.get_transformed_clip_path_and_affine())
+                            clippath, affine)
 
     def contains(self, mouseevent):
         """Test whether the mouse event occured within the image.

Modified: trunk/matplotlib/lib/matplotlib/patches.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/patches.py  2008-11-07 13:31:25 UTC (rev 
6371)
+++ trunk/matplotlib/lib/matplotlib/patches.py  2008-11-07 14:52:04 UTC (rev 
6372)
@@ -278,6 +278,7 @@
         gc.set_antialiased(self._antialiased)
         self._set_gc_clip(gc)
         gc.set_capstyle('projecting')
+        gc.set_url(self._url)
 
         if (not self.fill or self._facecolor is None or
             (cbook.is_string_like(self._facecolor) and 
self._facecolor.lower()=='none')):

Modified: trunk/matplotlib/lib/matplotlib/text.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/text.py     2008-11-07 13:31:25 UTC (rev 
6371)
+++ trunk/matplotlib/lib/matplotlib/text.py     2008-11-07 14:52:04 UTC (rev 
6372)
@@ -464,6 +464,7 @@
         gc = renderer.new_gc()
         gc.set_foreground(self._color)
         gc.set_alpha(self._alpha)
+        gc.set_url(self._url)
         if self.get_clip_on():
             gc.set_clip_rectangle(self.clipbox)
 

Modified: trunk/matplotlib/src/_backend_agg.cpp
===================================================================
--- trunk/matplotlib/src/_backend_agg.cpp       2008-11-07 13:31:25 UTC (rev 
6371)
+++ trunk/matplotlib/src/_backend_agg.cpp       2008-11-07 14:52:04 UTC (rev 
6372)
@@ -1154,7 +1154,7 @@
 Py::Object
 RendererAgg::draw_path_collection(const Py::Tuple& args) {
   _VERBOSE("RendererAgg::draw_path_collection");
-  args.verify_length(13);
+  args.verify_length(14);
 
   //segments, trans, clipbox, colors, linewidths, antialiaseds
   agg::trans_affine      master_transform = 
py_to_agg_transformation_matrix(args[0]);
@@ -1170,7 +1170,8 @@
   Py::SeqBase<Py::Float>  linewidths      = args[10];
   Py::SeqBase<Py::Object> linestyles_obj   = args[11];
   Py::SeqBase<Py::Int>    antialiaseds    = args[12];
-
+  // We don't actually care about urls for Agg, so just ignore it.
+  // Py::SeqBase<Py::Object> urls             = args[13];
   PathListGenerator path_generator(paths);
 
   try {


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to