~ubuntu-branches/ubuntu/gutsy/matplotlib/gutsy

« back to all changes in this revision

Viewing changes to lib/matplotlib/backend_bases.py

  • Committer: Bazaar Package Importer
  • Author(s): Michael Bienia
  • Date: 2007-07-31 23:04:56 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070731230456-lfmr0h69yh1i37w1
Tags: 0.90.1-2ubuntu1
* Merge from Debian unstable. Remaining changes:
  + debian/rules:
    - Check only the files for the python version which just got installed
      (fixes FTBFS).
    - Modify Maintainer value to match DebianMaintainerField spec.

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
from __future__ import division
7
7
import sys, warnings
8
8
 
9
 
from cbook import is_string_like, enumerate, strip_math, Stack
 
9
from cbook import is_string_like, enumerate, strip_math, Stack, CallbackRegistry
10
10
from colors import colorConverter
11
11
from numerix import array, sqrt, pi, log, asarray, ones, zeros, Float, Float32
12
12
from numerix import arange, compress, take, isnan, any
34
34
        pass
35
35
 
36
36
 
37
 
    def draw_arc(self, gc, rgbFace, x, y, width, height, angle1, angle2, rotation):
 
37
    def draw_arc(self, gc, rgbFace, x, y, width, height, angle1, angle2,
 
38
                 rotation):
38
39
        """
39
40
        Draw an arc using GraphicsContext instance gcEdge, centered at x,y,
40
41
        with width and height and angles from 0.0 to 360.0
48
49
 
49
50
    def get_image_magnification(self):
50
51
        """
51
 
        Get the factor by which to magnify images passed to draw_image.  
 
52
        Get the factor by which to magnify images passed to draw_image.
52
53
        Allows a backend to have images at a different resolution to other
53
54
        artists.
54
55
        """
255
256
        if clipbox is not None:
256
257
            gc.set_clip_rectangle(clipbox.get_bounds())
257
258
 
 
259
 
258
260
        for i in xrange(N):
259
261
            polyverts = verts[i % Nverts]
260
262
            if any(isnan(polyverts)):
467
469
        self._antialiased = 1  # use 0,1 not True, False for extension code
468
470
        self._capstyle = 'butt'
469
471
        self._cliprect = None
 
472
        self._clippath = None
470
473
        self._dashes = None, None
471
474
        self._joinstyle = 'miter'
472
475
        self._linestyle = 'solid'
480
483
        self._antialiased = gc._antialiased
481
484
        self._capstyle = gc._capstyle
482
485
        self._cliprect = gc._cliprect
 
486
        self._clippath = gc._clippath
483
487
        self._dashes = gc._dashes
484
488
        self._joinstyle = gc._joinstyle
485
489
        self._linestyle = gc._linestyle
510
514
        """
511
515
        return self._cliprect
512
516
 
 
517
    def get_clip_path(self):
 
518
        """
 
519
        Return the clip path
 
520
        """
 
521
        return self._clippath
 
522
 
513
523
    def get_dashes(self):
514
524
        """
515
525
        Return the dash information as an offset dashlist tuple The
577
587
        """
578
588
        self._cliprect = rectangle
579
589
 
 
590
    def set_clip_path(self, path):
 
591
        """
 
592
        Set the clip path
 
593
        """
 
594
        self._clippath = path
 
595
 
580
596
    def set_dashes(self, dash_offset, dash_list):
581
597
        """
582
598
        Set the dash style for the gc.
660
676
        self.canvas = canvas
661
677
        self.guiEvent = guiEvent
662
678
 
 
679
    
663
680
class DrawEvent(Event):
664
681
    """
665
682
    An event triggered by a draw operation on the canvas
778
795
        self.button = button
779
796
        self.key = key
780
797
 
 
798
class PickEvent(Event):
 
799
    """
 
800
    a pick event, fired when the user picks a location on the canvas
 
801
    sufficiently close to an artist.
 
802
 
 
803
    Attrs: all the Event attrs plus
 
804
    mouseevent : the MouseEvent that generated the pick
 
805
    artist    : the artist picked
 
806
 
 
807
    extra class dependent attrs -- eg a Line2D pick may define
 
808
    different extra attributes than a PatchCollection pick event
 
809
    """
 
810
    def __init__(self, name, canvas, mouseevent, artist, guiEvent=None, **kwargs):
 
811
        Event.__init__(self, name, canvas, guiEvent)
 
812
        self.mouseevent = mouseevent
 
813
        self.artist = artist
 
814
        self.__dict__.update(kwargs)
 
815
        
 
816
 
781
817
class KeyEvent(LocationEvent):
782
818
    """
783
819
    A key event (key press, key release).
812
848
 
813
849
      figure - A Figure instance
814
850
 
815
 
    """
 
851
      """
816
852
    events = (
 
853
        'resize_event',
 
854
        'draw_event',
817
855
        'key_press_event',
818
856
        'key_release_event',
819
857
        'button_press_event',
820
858
        'button_release_event',
821
859
        'motion_notify_event',
822
 
              )
 
860
        'pick_event', 
 
861
        )
 
862
 
823
863
 
824
864
    def __init__(self, figure):
825
865
        figure.set_canvas(self)
826
866
        self.figure = figure
827
 
        self.cid = 0
828
867
        # a dictionary from event name to a dictionary that maps cid->func
829
 
        self.callbacks = {}
 
868
        self.callbacks = CallbackRegistry(self.events)
830
869
        self.widgetlock = widgets.LockDraw()
831
870
        self._button     = None  # the button pressed
832
871
        self._key        = None  # the key pressed
846
885
        pass
847
886
 
848
887
    def draw_event(self, renderer):
849
 
        event = DrawEvent('draw_event', self, renderer)
850
 
        for func in self.callbacks.get('draw_event', {}).values():
851
 
            func(event)
 
888
        s = 'draw_event'
 
889
        event = DrawEvent(s, self, renderer)
 
890
        self.callbacks.process(s, event)
852
891
 
853
892
    def resize_event(self):
854
 
        event = ResizeEvent('resize_event', self)
855
 
        for func in self.callbacks.get('resize_event', {}).values():
856
 
            func(event)
 
893
        s = 'resize_event'
 
894
        event = ResizeEvent(s, self)
 
895
        self.callbacks.process(s, event)
857
896
 
858
897
    def key_press_event(self, key, guiEvent=None):
859
898
        self._key = key
860
 
        event = KeyEvent('key_press_event', self, key, self._lastx, self._lasty, guiEvent=guiEvent)
861
 
        for func in self.callbacks.get('key_press_event', {}).values():
862
 
            func(event)
 
899
        s = 'key_press_event'
 
900
        event = KeyEvent(s, self, key, self._lastx, self._lasty, guiEvent=guiEvent)
 
901
        self.callbacks.process(s, event)
863
902
 
864
903
    def key_release_event(self, key, guiEvent=None):
865
 
        event = KeyEvent('key_release_event', self, key, self._lastx, self._lasty, guiEvent=guiEvent)
866
 
        for func in self.callbacks.get('key_release_event', {}).values():
867
 
            func(event)
 
904
        s = 'key_release_event'
 
905
        event = KeyEvent(s, self, key, self._lastx, self._lasty, guiEvent=guiEvent)
 
906
        self.callbacks.process(s, event)
868
907
        self._key = None
869
908
 
 
909
    def pick_event(self, mouseevent, artist, **kwargs):
 
910
        """
 
911
        This method will be called by artists who are picked and will
 
912
        fire off PickEvent callbacks registered listeners
 
913
        """
 
914
        s = 'pick_event'
 
915
        event = PickEvent(s, self, mouseevent, artist, **kwargs)
 
916
        self.callbacks.process(s, event)
 
917
            
870
918
    def button_press_event(self, x, y, button, guiEvent=None):
871
919
        """
872
920
        Backend derived classes should call this function on any mouse
874
922
        button and key are as defined in MouseEvent
875
923
        """
876
924
        self._button = button
877
 
        event = MouseEvent('button_press_event', self, x, y, button, self._key, guiEvent=guiEvent)
878
 
        for func in self.callbacks.get('button_press_event', {}).values():
879
 
            func(event)
880
 
 
 
925
        s = 'button_press_event'
 
926
        mouseevent = MouseEvent(s, self, x, y, button, self._key, guiEvent=guiEvent)
 
927
        self.callbacks.process(s, mouseevent)
 
928
 
 
929
 
 
930
        if not self.widgetlock.locked():
 
931
            self.figure.pick(mouseevent)
 
932
        
881
933
    def button_release_event(self, x, y, button, guiEvent=None):
882
934
        """
883
935
        Backend derived classes should call this function on any mouse
884
936
        button release.  x,y are the canvas coords: 0,0 is lower, left.
885
937
        button and key are as defined in MouseEvent
886
938
        """
887
 
 
888
 
        event = MouseEvent('button_release_event', self, x, y, button, self._key, guiEvent=guiEvent)
889
 
        for func in self.callbacks.get('button_release_event', {}).values():
890
 
            func(event)
 
939
        s = 'button_release_event'
 
940
        event = MouseEvent(s, self, x, y, button, self._key, guiEvent=guiEvent)
 
941
        self.callbacks.process(s, event)
891
942
        self._button = None
892
943
 
893
944
    def motion_notify_event(self, x, y, guiEvent=None):
897
948
        button and key are as defined in MouseEvent
898
949
        """
899
950
        self._lastx, self._lasty = x, y
900
 
        event = MouseEvent('motion_notify_event', self, x, y, self._button, self._key, guiEvent=guiEvent)
901
 
        for func in self.callbacks.get('motion_notify_event', {}).values():
902
 
            func(event)
 
951
        s = 'motion_notify_event'
 
952
        event = MouseEvent(s, self, x, y, self._button, self._key,
 
953
                           guiEvent=guiEvent)
 
954
        self.callbacks.process(s, event)
903
955
 
904
956
    def draw(self, *args, **kwargs):
905
957
        """
936
988
        filename    - can also be a file object on image backends
937
989
        orientation - only currently applies to PostScript printing.
938
990
        dpi - the dots per inch to save the figure in; if None, use savefig.dpi
 
991
        facecolor - the facecolor of the figure
 
992
        edgecolor - the edgecolor of the figure
 
993
        orientation - 'landscape' | 'portrait' (not supported on all backends)
939
994
        """
940
995
        pass
941
996
 
959
1014
 
960
1015
        where event is a MplEvent.  The following events are recognized
961
1016
 
962
 
         'resize_event'
963
 
         'draw_event'
964
 
         'key_press_event'
965
 
         'key_release_event'
966
 
         'button_press_event'
967
 
         'button_release_event'
968
 
         'motion_notify_event'
969
 
 
970
 
         For the three events above, if the mouse is over the axes,
971
 
         the variable event.inaxes will be set to the axes it is over,
972
 
         and additionally, the variables event.xdata and event.ydata
973
 
         will be defined.  This is the mouse location in data coords.
974
 
         See backend_bases.MplEvent.
975
 
 
 
1017
        'resize_event',
 
1018
        'draw_event',
 
1019
        'key_press_event',
 
1020
        'key_release_event',
 
1021
        'button_press_event',
 
1022
        'button_release_event',
 
1023
        'motion_notify_event',
 
1024
        'pick_event', 
 
1025
        
 
1026
        
 
1027
        For the three events above, if the mouse is over the axes,
 
1028
        the variable event.inaxes will be set to the axes it is over,
 
1029
        and additionally, the variables event.xdata and event.ydata
 
1030
        will be defined.  This is the mouse location in data coords.
 
1031
        See backend_bases.MplEvent.
 
1032
        
976
1033
        return value is a connection id that can be used with
977
1034
        mpl_disconnect """
978
1035
 
979
 
        legit = (
980
 
        'resize_event',
981
 
        'draw_event',
982
 
        'key_press_event',
983
 
        'key_release_event',
984
 
        'button_press_event',
985
 
        'button_release_event',
986
 
        'motion_notify_event',
987
 
        )
988
 
 
989
 
        if s not in legit: raise ValueError('Unrecognized event "%s"'%s)
990
 
        self.cid += 1
991
 
        self.callbacks.setdefault(s, {})[self.cid] = func
992
 
        return self.cid
 
1036
        return self.callbacks.connect(s, func)
993
1037
 
994
1038
    def mpl_disconnect(self, cid):
995
1039
        """
996
 
        Connect s to func. return an id that can be used with disconnect
997
 
        Method should return None
 
1040
        disconnect callback id cid
998
1041
        """
999
 
        for eventname, callbackd in self.callbacks.items():
1000
 
            if callbackd.has_key(cid):
1001
 
                del callbackd[cid]
1002
 
                return
 
1042
        return self.callbacks.disconnect(cid)        
1003
1043
 
1004
1044
 
1005
1045
class FigureManagerBase:
1022
1062
 
1023
1063
    def full_screen_toggle (self):
1024
1064
        pass
1025
 
    
 
1065
 
1026
1066
    def resize(self, w, h):
1027
1067
        'For gui backends: resize window in pixels'
1028
1068
        pass
1029
 
    
 
1069
 
1030
1070
    def key_press(self, event):
1031
1071
 
1032
1072
        # these bindings happen whether you are over an axes or not
1111
1151
 
1112
1152
    def __init__(self, canvas):
1113
1153
        self.canvas = canvas
1114
 
 
 
1154
        canvas.toolbar = self
1115
1155
        # a dict from axes index to a list of view limits
1116
1156
        self._views = Stack()
1117
1157
        self._positions = Stack()  # stack of subplot positions
1414
1454
                except OverflowError:
1415
1455
                    warnings.warn('Overflow while panning')
1416
1456
                    return
1417
 
            a.set_xlim(self.nonsingular(xmin, xmax))
1418
 
            a.set_ylim(self.nonsingular(ymin, ymax))
 
1457
            a.set_xlim(xmin, xmax)
 
1458
            a.set_ylim(ymin, ymax)
1419
1459
 
1420
1460
        self.dynamic_update()
1421
1461
 
1422
 
    def nonsingular(self, x0, x1):
1423
 
        '''Desperate hack to prevent crashes when button-3 panning with
1424
 
        axis('image') in effect.
1425
 
        '''
1426
 
        d = x1 - x0
1427
 
        # much smaller thresholds seem to cause Value Error
1428
 
        # later in Transformation::freeze in axes.draw()
1429
 
        if abs(d) < 1e-10:
1430
 
            warnings.warn('Axis data limit is too small for panning')
1431
 
            x1 += 1e-10
1432
 
            x0 -= 1e-10
1433
 
        return (x0, x1)
1434
 
 
1435
 
 
1436
1462
    def release_zoom(self, event):
1437
1463
        'the release mouse button callback in zoom to rect mode'
1438
1464
        if not self._xypress: return