Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b3ba921

Browse files
committed
Combine common GTK toolbar code.
1 parent e4df0eb commit b3ba921

File tree

3 files changed

+92
-151
lines changed

3 files changed

+92
-151
lines changed

lib/matplotlib/backends/_backend_gtk.py

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
import logging
66

77
import matplotlib as mpl
8-
from matplotlib import cbook
8+
from matplotlib import backend_tools, cbook
99
from matplotlib.backend_bases import (
10-
_Backend, TimerBase,
10+
_Backend, NavigationToolbar2, TimerBase,
1111
)
1212

1313
# The GTK3/GTK4 backends will have already called `gi.require_version` to set
@@ -98,6 +98,77 @@ def _on_timer(self):
9898
return False
9999

100100

101+
class _NavigationToolbar2GTK(NavigationToolbar2):
102+
# Must be implemented in GTK3/GTK4 backends:
103+
# * __init__
104+
# * save_figure
105+
106+
def set_message(self, s):
107+
escaped = GLib.markup_escape_text(s)
108+
self.message.set_markup(f'<small>{escaped}</small>')
109+
110+
def draw_rubberband(self, event, x0, y0, x1, y1):
111+
height = self.canvas.figure.bbox.height
112+
y1 = height - y1
113+
y0 = height - y0
114+
rect = [int(val) for val in (x0, y0, x1 - x0, y1 - y0)]
115+
self.canvas._draw_rubberband(rect)
116+
117+
def remove_rubberband(self):
118+
self.canvas._draw_rubberband(None)
119+
120+
def _update_buttons_checked(self):
121+
for name, active in [("Pan", "PAN"), ("Zoom", "ZOOM")]:
122+
button = self._gtk_ids.get(name)
123+
should_be_active = self.mode.name == active
124+
if button and button.get_active() != should_be_active:
125+
button.set_active(should_be_active)
126+
127+
def pan(self, *args):
128+
super().pan(*args)
129+
self._update_buttons_checked()
130+
131+
def zoom(self, *args):
132+
super().zoom(*args)
133+
self._update_buttons_checked()
134+
135+
def set_history_buttons(self):
136+
can_backward = self._nav_stack._pos > 0
137+
can_forward = self._nav_stack._pos < len(self._nav_stack._elements) - 1
138+
if 'Back' in self._gtk_ids:
139+
self._gtk_ids['Back'].set_sensitive(can_backward)
140+
if 'Forward' in self._gtk_ids:
141+
self._gtk_ids['Forward'].set_sensitive(can_forward)
142+
143+
144+
class RubberbandGTK(backend_tools.RubberbandBase):
145+
def draw_rubberband(self, x0, y0, x1, y1):
146+
_NavigationToolbar2GTK.draw_rubberband(
147+
self._make_classic_style_pseudo_toolbar(), None, x0, y0, x1, y1)
148+
149+
def remove_rubberband(self):
150+
_NavigationToolbar2GTK.remove_rubberband(
151+
self._make_classic_style_pseudo_toolbar())
152+
153+
154+
class SaveFigureGTK(backend_tools.SaveFigureBase):
155+
def trigger(self, *args, **kwargs):
156+
157+
class PseudoToolbar:
158+
canvas = self.figure.canvas
159+
160+
return _NavigationToolbar2GTK.save_figure(PseudoToolbar())
161+
162+
163+
class ConfigureSubplotsGTK(backend_tools.ConfigureSubplotsBase, Gtk.Window):
164+
def _get_canvas(self, fig):
165+
return self.canvas.__class__(fig)
166+
167+
def trigger(self, *args):
168+
_NavigationToolbar2GTK.configure_subplots(
169+
self._make_classic_style_pseudo_toolbar(), None)
170+
171+
101172
class _BackendGTK(_Backend):
102173
@staticmethod
103174
def mainloop():

lib/matplotlib/backends/backend_gtk3.py

Lines changed: 13 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,11 @@
3131
from gi.repository import Gio, GLib, GObject, Gtk, Gdk
3232
from ._backend_gtk import (
3333
_create_application, _shutdown_application,
34-
backend_version, _BackendGTK,
34+
backend_version, _BackendGTK, _NavigationToolbar2GTK,
3535
TimerGTK as TimerGTK3,
36+
ConfigureSubplotsGTK as ConfigureSubplotsGTK3,
37+
RubberbandGTK as RubberbandGTK3,
38+
SaveFigureGTK as SaveFigureGTK3,
3639
)
3740

3841

@@ -284,7 +287,7 @@ class FigureManagerGTK3(FigureManagerBase):
284287
num : int or str
285288
The Figure number
286289
toolbar : Gtk.Toolbar
287-
The Gtk.Toolbar
290+
The toolbar
288291
vbox : Gtk.VBox
289292
The Gtk.VBox containing the canvas and toolbar
290293
window : Gtk.Window
@@ -411,7 +414,7 @@ def resize(self, width, height):
411414
self.window.resize(width, height)
412415

413416

414-
class NavigationToolbar2GTK3(NavigationToolbar2, Gtk.Toolbar):
417+
class NavigationToolbar2GTK3(_NavigationToolbar2GTK, Gtk.Toolbar):
415418
def __init__(self, canvas, window):
416419
self.win = window
417420
GObject.GObject.__init__(self)
@@ -428,21 +431,14 @@ def __init__(self, canvas, window):
428431
str(cbook._get_data_path('images',
429432
f'{image_file}-symbolic.svg'))),
430433
Gtk.IconSize.LARGE_TOOLBAR)
431-
self._gtk_ids[text] = tbutton = (
434+
self._gtk_ids[text] = button = (
432435
Gtk.ToggleToolButton() if callback in ['zoom', 'pan'] else
433436
Gtk.ToolButton())
434-
tbutton.set_label(text)
435-
tbutton.set_icon_widget(image)
436-
self.insert(tbutton, -1)
437-
# Save the handler id, so that we can block it as needed.
438-
tbutton._signal_handler = tbutton.connect(
439-
'clicked', getattr(self, callback))
440-
tbutton.set_tooltip_text(tooltip_text)
441-
442-
toolitem = Gtk.SeparatorToolItem()
443-
self.insert(toolitem, -1)
444-
toolitem.set_draw(False)
445-
toolitem.set_expand(True)
437+
button.set_label(text)
438+
button.set_icon_widget(image)
439+
button.connect('clicked', getattr(self, callback))
440+
button.set_tooltip_text(tooltip_text)
441+
self.insert(button, -1)
446442

447443
# This filler item ensures the toolbar is always at least two text
448444
# lines high. Otherwise the canvas gets redrawn as the mouse hovers
@@ -453,6 +449,7 @@ def __init__(self, canvas, window):
453449
label = Gtk.Label()
454450
label.set_markup(
455451
'<small>\N{NO-BREAK SPACE}\n\N{NO-BREAK SPACE}</small>')
452+
toolitem.set_expand(True) # Push real message to the right.
456453
toolitem.add(label)
457454

458455
toolitem = Gtk.ToolItem()
@@ -464,35 +461,6 @@ def __init__(self, canvas, window):
464461

465462
NavigationToolbar2.__init__(self, canvas)
466463

467-
def set_message(self, s):
468-
escaped = GLib.markup_escape_text(s)
469-
self.message.set_markup(f'<small>{escaped}</small>')
470-
471-
def draw_rubberband(self, event, x0, y0, x1, y1):
472-
height = self.canvas.figure.bbox.height
473-
y1 = height - y1
474-
y0 = height - y0
475-
rect = [int(val) for val in (x0, y0, x1 - x0, y1 - y0)]
476-
self.canvas._draw_rubberband(rect)
477-
478-
def remove_rubberband(self):
479-
self.canvas._draw_rubberband(None)
480-
481-
def _update_buttons_checked(self):
482-
for name, active in [("Pan", "PAN"), ("Zoom", "ZOOM")]:
483-
button = self._gtk_ids.get(name)
484-
if button:
485-
with button.handler_block(button._signal_handler):
486-
button.set_active(self.mode.name == active)
487-
488-
def pan(self, *args):
489-
super().pan(*args)
490-
self._update_buttons_checked()
491-
492-
def zoom(self, *args):
493-
super().zoom(*args)
494-
self._update_buttons_checked()
495-
496464
def save_figure(self, *args):
497465
dialog = Gtk.FileChooserDialog(
498466
title="Save the figure",
@@ -537,14 +505,6 @@ def on_notify_filter(*args):
537505
except Exception as e:
538506
error_msg_gtk(str(e), parent=self)
539507

540-
def set_history_buttons(self):
541-
can_backward = self._nav_stack._pos > 0
542-
can_forward = self._nav_stack._pos < len(self._nav_stack._elements) - 1
543-
if 'Back' in self._gtk_ids:
544-
self._gtk_ids['Back'].set_sensitive(can_backward)
545-
if 'Forward' in self._gtk_ids:
546-
self._gtk_ids['Forward'].set_sensitive(can_forward)
547-
548508

549509
class ToolbarGTK3(ToolContainerBase, Gtk.Box):
550510
_icon_extension = '-symbolic.svg'
@@ -626,41 +586,13 @@ def set_message(self, s):
626586
self._message.set_label(s)
627587

628588

629-
class RubberbandGTK3(backend_tools.RubberbandBase):
630-
def draw_rubberband(self, x0, y0, x1, y1):
631-
NavigationToolbar2GTK3.draw_rubberband(
632-
self._make_classic_style_pseudo_toolbar(), None, x0, y0, x1, y1)
633-
634-
def remove_rubberband(self):
635-
NavigationToolbar2GTK3.remove_rubberband(
636-
self._make_classic_style_pseudo_toolbar())
637-
638-
639-
class SaveFigureGTK3(backend_tools.SaveFigureBase):
640-
def trigger(self, *args, **kwargs):
641-
642-
class PseudoToolbar:
643-
canvas = self.figure.canvas
644-
645-
return NavigationToolbar2GTK3.save_figure(PseudoToolbar())
646-
647-
648589
@_api.deprecated("3.5", alternative="ToolSetCursor")
649590
class SetCursorGTK3(backend_tools.SetCursorBase):
650591
def set_cursor(self, cursor):
651592
NavigationToolbar2GTK3.set_cursor(
652593
self._make_classic_style_pseudo_toolbar(), cursor)
653594

654595

655-
class ConfigureSubplotsGTK3(backend_tools.ConfigureSubplotsBase, Gtk.Window):
656-
def _get_canvas(self, fig):
657-
return self.canvas.__class__(fig)
658-
659-
def trigger(self, *args):
660-
NavigationToolbar2GTK3.configure_subplots(
661-
self._make_classic_style_pseudo_toolbar(), None)
662-
663-
664596
class HelpGTK3(backend_tools.ToolHelpBase):
665597
def _normalize_shortcut(self, key):
666598
"""

lib/matplotlib/backends/backend_gtk4.py

Lines changed: 6 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,11 @@
3232
from gi.repository import Gio, GLib, GObject, Gtk, Gdk, GdkPixbuf
3333
from ._backend_gtk import (
3434
_create_application, _shutdown_application,
35-
backend_version, _BackendGTK,
35+
backend_version, _BackendGTK, _NavigationToolbar2GTK,
3636
TimerGTK as TimerGTK4,
37+
ConfigureSubplotsGTK as ConfigureSubplotsGTK4,
38+
RubberbandGTK as RubberbandGTK4,
39+
SaveFigureGTK as SaveFigureGTK4,
3740
)
3841

3942

@@ -249,7 +252,7 @@ class FigureManagerGTK4(FigureManagerBase):
249252
num : int or str
250253
The Figure number
251254
toolbar : Gtk.Box
252-
The Gtk.Box
255+
The toolbar
253256
vbox : Gtk.VBox
254257
The Gtk.VBox containing the canvas and toolbar
255258
window : Gtk.Window
@@ -367,7 +370,7 @@ def resize(self, width, height):
367370
self.window.resize(width, height)
368371

369372

370-
class NavigationToolbar2GTK4(NavigationToolbar2, Gtk.Box):
373+
class NavigationToolbar2GTK4(_NavigationToolbar2GTK, Gtk.Box):
371374
def __init__(self, canvas, window):
372375
self.win = window
373376
Gtk.Box.__init__(self)
@@ -408,35 +411,6 @@ def __init__(self, canvas, window):
408411

409412
NavigationToolbar2.__init__(self, canvas)
410413

411-
def set_message(self, s):
412-
escaped = GLib.markup_escape_text(s)
413-
self.message.set_markup(f'<small>{escaped}</small>')
414-
415-
def draw_rubberband(self, event, x0, y0, x1, y1):
416-
height = self.canvas.figure.bbox.height
417-
y1 = height - y1
418-
y0 = height - y0
419-
rect = [int(val) for val in (x0, y0, x1 - x0, y1 - y0)]
420-
self.canvas._draw_rubberband(rect)
421-
422-
def remove_rubberband(self):
423-
self.canvas._draw_rubberband(None)
424-
425-
def _update_buttons_checked(self):
426-
for name, active in [("Pan", "PAN"), ("Zoom", "ZOOM")]:
427-
button = self._gtk_ids.get(name)
428-
should_be_active = self.mode.name == active
429-
if button and button.get_active() != should_be_active:
430-
button.set_active(should_be_active)
431-
432-
def pan(self, *args):
433-
super().pan(*args)
434-
self._update_buttons_checked()
435-
436-
def zoom(self, *args):
437-
super().zoom(*args)
438-
self._update_buttons_checked()
439-
440414
def save_figure(self, *args):
441415
dialog = Gtk.FileChooserNative(
442416
title='Save the figure',
@@ -499,14 +473,6 @@ def on_response(dialog, response):
499473

500474
dialog.show()
501475

502-
def set_history_buttons(self):
503-
can_backward = self._nav_stack._pos > 0
504-
can_forward = self._nav_stack._pos < len(self._nav_stack._elements) - 1
505-
if 'Back' in self._gtk_ids:
506-
self._gtk_ids['Back'].set_sensitive(can_backward)
507-
if 'Forward' in self._gtk_ids:
508-
self._gtk_ids['Forward'].set_sensitive(can_forward)
509-
510476

511477
class ToolbarGTK4(ToolContainerBase, Gtk.Box):
512478
_icon_extension = '-symbolic.svg'
@@ -608,34 +574,6 @@ def set_message(self, s):
608574
self._message.set_label(s)
609575

610576

611-
class RubberbandGTK4(backend_tools.RubberbandBase):
612-
def draw_rubberband(self, x0, y0, x1, y1):
613-
NavigationToolbar2GTK4.draw_rubberband(
614-
self._make_classic_style_pseudo_toolbar(), None, x0, y0, x1, y1)
615-
616-
def remove_rubberband(self):
617-
NavigationToolbar2GTK4.remove_rubberband(
618-
self._make_classic_style_pseudo_toolbar())
619-
620-
621-
class SaveFigureGTK4(backend_tools.SaveFigureBase):
622-
def trigger(self, *args, **kwargs):
623-
624-
class PseudoToolbar:
625-
canvas = self.figure.canvas
626-
627-
return NavigationToolbar2GTK4.save_figure(PseudoToolbar())
628-
629-
630-
class ConfigureSubplotsGTK4(backend_tools.ConfigureSubplotsBase, Gtk.Window):
631-
def _get_canvas(self, fig):
632-
return self.canvas.__class__(fig)
633-
634-
def trigger(self, *args):
635-
NavigationToolbar2GTK4.configure_subplots(
636-
self._make_classic_style_pseudo_toolbar(), None)
637-
638-
639577
class HelpGTK4(backend_tools.ToolHelpBase):
640578
def _normalize_shortcut(self, key):
641579
"""

0 commit comments

Comments
 (0)