@@ -417,6 +417,7 @@ def __init__(self, ax, mappable=None, *, cmap=None,
417417 self ._filled = filled
418418 self .extendfrac = extendfrac
419419 self .extendrect = extendrect
420+ self ._extend_patches = []
420421 self .solids = None
421422 self .solids_patches = []
422423 self .lines = []
@@ -483,6 +484,11 @@ def __init__(self, ax, mappable=None, *, cmap=None,
483484 setattr (self .ax , x , getattr (self , x ))
484485 # Set the cla function to the cbar's method to override it
485486 self .ax .cla = self ._cbar_cla
487+ # Callbacks for the extend calculations to handle inverting the axis
488+ self ._extend_cid1 = self .ax .callbacks .connect (
489+ "xlim_changed" , self ._do_extends )
490+ self ._extend_cid2 = self .ax .callbacks .connect (
491+ "ylim_changed" , self ._do_extends )
486492
487493 @property
488494 def locator (self ):
@@ -598,17 +604,20 @@ def _draw_all(self):
598604 # extensions:
599605 self .vmin , self .vmax = self ._boundaries [self ._inside ][[0 , - 1 ]]
600606 # Compute the X/Y mesh.
601- X , Y , extendlen = self ._mesh ()
607+ X , Y = self ._mesh ()
602608 # draw the extend triangles, and shrink the inner axes to accommodate.
603609 # also adds the outline path to self.outline spine:
604- self ._do_extends (extendlen )
605-
610+ self ._do_extends ()
611+ lower , upper = self .vmin , self .vmax
612+ if self ._long_axis ().get_inverted ():
613+ # If the axis is inverted, we need to swap the vmin/vmax
614+ lower , upper = upper , lower
606615 if self .orientation == 'vertical' :
607616 self .ax .set_xlim (0 , 1 )
608- self .ax .set_ylim (self . vmin , self . vmax )
617+ self .ax .set_ylim (lower , upper )
609618 else :
610619 self .ax .set_ylim (0 , 1 )
611- self .ax .set_xlim (self . vmin , self . vmax )
620+ self .ax .set_xlim (lower , upper )
612621
613622 # set up the tick locators and formatters. A bit complicated because
614623 # boundary norms + uniform spacing requires a manual locator.
@@ -661,12 +670,19 @@ def _add_solids_patches(self, X, Y, C, mappable):
661670 patches .append (patch )
662671 self .solids_patches = patches
663672
664- def _do_extends (self , extendlen ):
673+ def _do_extends (self , ax = None ):
665674 """
666675 Add the extend tri/rectangles on the outside of the axes.
676+
677+ ax is unused, but required due to the callbacks on xlim/ylim changed
667678 """
679+ # Clean up any previous extend patches
680+ for patch in self ._extend_patches :
681+ patch .remove ()
682+ self ._extend_patches = []
668683 # extend lengths are fraction of the *inner* part of colorbar,
669684 # not the total colorbar:
685+ _ , extendlen = self ._proportional_y ()
670686 bot = 0 - (extendlen [0 ] if self ._extend_lower () else 0 )
671687 top = 1 + (extendlen [1 ] if self ._extend_upper () else 0 )
672688
@@ -708,12 +724,17 @@ def _do_extends(self, extendlen):
708724 if self .orientation == 'horizontal' :
709725 xy = xy [:, ::- 1 ]
710726 # add the patch
711- color = self .cmap (self .norm (self ._values [0 ]))
727+ val = - 1 if self ._long_axis ().get_inverted () else 0
728+ color = self .cmap (self .norm (self ._values [val ]))
712729 patch = mpatches .PathPatch (
713730 mpath .Path (xy ), facecolor = color , linewidth = 0 ,
714731 antialiased = False , transform = self .ax .transAxes ,
715- hatch = hatches [0 ], clip_on = False )
732+ hatch = hatches [0 ], clip_on = False ,
733+ # Place it right behind the standard patches, which is
734+ # needed if we updated the extends
735+ zorder = np .nextafter (self .ax .patch .zorder , - np .inf ))
716736 self .ax .add_patch (patch )
737+ self ._extend_patches .append (patch )
717738 if self ._extend_upper ():
718739 if not self .extendrect :
719740 # triangle
@@ -724,12 +745,17 @@ def _do_extends(self, extendlen):
724745 if self .orientation == 'horizontal' :
725746 xy = xy [:, ::- 1 ]
726747 # add the patch
727- color = self .cmap (self .norm (self ._values [- 1 ]))
748+ val = 0 if self ._long_axis ().get_inverted () else - 1
749+ color = self .cmap (self .norm (self ._values [val ]))
728750 patch = mpatches .PathPatch (
729751 mpath .Path (xy ), facecolor = color ,
730752 linewidth = 0 , antialiased = False ,
731- transform = self .ax .transAxes , hatch = hatches [- 1 ], clip_on = False )
753+ transform = self .ax .transAxes , hatch = hatches [- 1 ], clip_on = False ,
754+ # Place it right behind the standard patches, which is
755+ # needed if we updated the extends
756+ zorder = np .nextafter (self .ax .patch .zorder , - np .inf ))
732757 self .ax .add_patch (patch )
758+ self ._extend_patches .append (patch )
733759 return
734760
735761 def add_lines (self , * args , ** kwargs ):
@@ -1049,6 +1075,9 @@ def remove(self):
10491075 self .mappable .callbacks .disconnect (self .mappable .colorbar_cid )
10501076 self .mappable .colorbar = None
10511077 self .mappable .colorbar_cid = None
1078+ # Remove the extension callbacks
1079+ self .ax .callbacks .disconnect (self ._extend_cid1 )
1080+ self .ax .callbacks .disconnect (self ._extend_cid2 )
10521081
10531082 try :
10541083 ax = self .mappable .axes
@@ -1151,7 +1180,7 @@ def _mesh(self):
11511180 These are scaled between vmin and vmax, and already handle colorbar
11521181 orientation.
11531182 """
1154- y , extendlen = self ._proportional_y ()
1183+ y , _ = self ._proportional_y ()
11551184 # Use the vmin and vmax of the colorbar, which may not be the same
11561185 # as the norm. There are situations where the colormap has a
11571186 # narrower range than the colorbar and we want to accommodate the
@@ -1172,9 +1201,9 @@ def _mesh(self):
11721201 self ._y = y
11731202 X , Y = np .meshgrid ([0. , 1. ], y )
11741203 if self .orientation == 'vertical' :
1175- return (X , Y , extendlen )
1204+ return (X , Y )
11761205 else :
1177- return (Y , X , extendlen )
1206+ return (Y , X )
11781207
11791208 def _forward_boundaries (self , x ):
11801209 # map boundaries equally between 0 and 1...
@@ -1322,11 +1351,13 @@ def _get_extension_lengths(self, frac, automin, automax, default=0.05):
13221351
13231352 def _extend_lower (self ):
13241353 """Return whether the lower limit is open ended."""
1325- return self .extend in ('both' , 'min' )
1354+ minmax = "max" if self ._long_axis ().get_inverted () else "min"
1355+ return self .extend in ('both' , minmax )
13261356
13271357 def _extend_upper (self ):
13281358 """Return whether the upper limit is open ended."""
1329- return self .extend in ('both' , 'max' )
1359+ minmax = "min" if self ._long_axis ().get_inverted () else "max"
1360+ return self .extend in ('both' , minmax )
13301361
13311362 def _long_axis (self ):
13321363 """Return the long axis"""
0 commit comments