Skip to content

Commit 03d0f37

Browse files
committed
implement xtick rotation_mode
1 parent 0439b37 commit 03d0f37

File tree

4 files changed

+57
-2
lines changed

4 files changed

+57
-2
lines changed

lib/matplotlib/axis.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,11 @@ def _apply_params(self, **kwargs):
346346
if k in _gridline_param_names}
347347
self.gridline.set(**grid_kw)
348348

349+
if 'rotation_mode' in kwargs:
350+
rotation_mode = kwargs.pop('rotation_mode')
351+
self.label1.set_rotation_mode(rotation_mode)
352+
self.label2.set_rotation_mode(rotation_mode)
353+
349354
def update_position(self, loc):
350355
"""Set the location of tick in data coords with scalar *loc*."""
351356
raise NotImplementedError('Derived must override')
@@ -1072,7 +1077,7 @@ def _translate_tick_params(kw, reverse=False):
10721077
'tick1On', 'tick2On', 'label1On', 'label2On',
10731078
'length', 'direction', 'left', 'bottom', 'right', 'top',
10741079
'labelleft', 'labelbottom', 'labelright', 'labeltop',
1075-
'labelrotation',
1080+
'labelrotation', 'rotation_mode',
10761081
*_gridline_param_names]
10771082

10781083
keymap = {

lib/matplotlib/tests/test_text.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,3 +1135,19 @@ def test_font_wrap():
11351135
plt.text(3, 4, t, family='monospace', ha='right', wrap=True)
11361136
plt.text(-1, 0, t, fontsize=14, style='italic', ha='left', rotation=-15,
11371137
wrap=True)
1138+
1139+
1140+
def test_ha_for_angle():
1141+
text_instance = Text()
1142+
angles = np.arange(0, 360.1, 0.1)
1143+
for angle in angles:
1144+
alignment = text_instance.ha_for_angle(angle)
1145+
assert alignment in ['center', 'left', 'right']
1146+
1147+
1148+
def test_va_for_angle():
1149+
text_instance = Text()
1150+
angles = np.arange(0, 360.1, 0.1)
1151+
for angle in angles:
1152+
alignment = text_instance.va_for_angle(angle)
1153+
assert alignment in ['center', 'top', 'bottom']

lib/matplotlib/text.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ def set_rotation_mode(self, m):
310310
if m is None:
311311
m = "default"
312312
else:
313-
_api.check_in_list(("anchor", "default"), rotation_mode=m)
313+
_api.check_in_list(("anchor", "default", "xtick", "ytick"), rotation_mode=m)
314314
self._rotation_mode = m
315315
self.stale = True
316316

@@ -454,6 +454,12 @@ def _get_layout(self, renderer):
454454

455455
rotation_mode = self.get_rotation_mode()
456456
if rotation_mode != "anchor":
457+
if rotation_mode == 'xtick':
458+
angle = self.get_rotation()
459+
halign = self.ha_for_angle(angle)
460+
elif rotation_mode == 'ytick':
461+
angle = self.get_rotation()
462+
valign = self.va_for_angle(angle)
457463
# compute the text location in display coords and the offsets
458464
# necessary to align the bbox with that location
459465
if halign == 'center':
@@ -467,6 +473,8 @@ def _get_layout(self, renderer):
467473
offsety = (ymin + ymax) / 2
468474
elif valign == 'top':
469475
offsety = ymax
476+
elif valign == 'bottom':
477+
offsety = ymin
470478
elif valign == 'baseline':
471479
offsety = ymin + descent
472480
elif valign == 'center_baseline':
@@ -1380,6 +1388,30 @@ def set_fontname(self, fontname):
13801388
"""
13811389
self.set_fontfamily(fontname)
13821390

1391+
def ha_for_angle(self, angle):
1392+
"""
1393+
Determines horizontal alignment ('ha') based on the angle of rotation.
1394+
"""
1395+
if (angle < 5 or 85 <= angle < 105 or 355 <= angle <= 360 or
1396+
170 <= angle < 190 or 265 <= angle < 275):
1397+
return 'center'
1398+
elif 5 <= angle < 85 or 190 <= angle < 265:
1399+
return 'right'
1400+
elif 105 <= angle < 170 or 275 <= angle < 355:
1401+
return 'left'
1402+
1403+
def va_for_angle(self, angle):
1404+
"""
1405+
Determines vertical alignment ('va') based on the angle of rotation.
1406+
"""
1407+
if (angle < 5 or 355 <= angle <= 360 or 170 <= angle < 190
1408+
or 85 <= angle < 105 or 265 <= angle < 275):
1409+
return 'center'
1410+
elif 190 <= angle < 265 or 5 <= angle < 85:
1411+
return 'top'
1412+
elif 105 <= angle < 170 or 275 <= angle < 355:
1413+
return 'bottom'
1414+
13831415

13841416
class OffsetFrom:
13851417
"""Callable helper class for working with `Annotation`."""

lib/matplotlib/text.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ class Text(Artist):
106106
def set_fontname(self, fontname: str | Iterable[str]) -> None: ...
107107
def get_antialiased(self) -> bool: ...
108108
def set_antialiased(self, antialiased: bool) -> None: ...
109+
def ha_for_angle(self, angle: Any) -> Literal['center', 'right', 'left'] | None: ...
110+
def va_for_angle(self, angle: Any) -> Literal['center', 'top', 'bottom'] | None: ...
109111

110112
class OffsetFrom:
111113
def __init__(

0 commit comments

Comments
 (0)