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

Skip to content

Backend refactor #8777

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 58 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
9813e43
Refactor pass 1. Refactoring Gcf out of specific backend (backend_gt…
OceanWolf Feb 21, 2015
91cbffc
Refactor Pass 2. Refactored Gcf out of all backend code.
OceanWolf Feb 22, 2015
aa3ff59
Quick fix to figure for safe unpickling.
OceanWolf Feb 25, 2015
f046e01
GTK3Agg
OceanWolf Feb 26, 2015
39ff708
Refactored making `FigureManager` a *figure* manager, plus added miss…
OceanWolf Feb 27, 2015
45c5fc2
keyword
OceanWolf Feb 27, 2015
ebf0c57
Make add_element more general, and make sure the code complies with it.
OceanWolf Feb 27, 2015
9d25441
Better destroy order.
OceanWolf Feb 27, 2015
6ae52f2
GTK simplifications
OceanWolf Feb 28, 2015
1a47d3b
Added doc and cleaned backend_managers, don't want our new file dirty.
OceanWolf Mar 3, 2015
bc17372
Improve layout!
OceanWolf Apr 6, 2015
3fb46f2
Move knowledge of the backend to the manager.
OceanWolf Apr 7, 2015
2758f3f
Incorporate MEP22 into MEP27
OceanWolf Apr 12, 2015
f354d3c
Improved new toolbar and updated tool_manager example accoridingly.
OceanWolf Apr 12, 2015
51c0598
fullscreen
OceanWolf Apr 13, 2015
6b35d85
MEP update
OceanWolf Apr 14, 2015
724b622
Finish MEP22 conversion
OceanWolf Apr 14, 2015
0b42bbe
rename window method
OceanWolf Apr 17, 2015
ef65740
Add backend anme to widgets
OceanWolf Apr 17, 2015
fb5202a
Handle FigureManager destroy internaly without pyplot.
OceanWolf Jun 4, 2015
26ce3e6
Make functionality more consistant for embedded applications
OceanWolf Jun 7, 2015
1cfebc4
Backend getter method for FigureManager
OceanWolf Jun 13, 2015
bc32fb1
Improve example after new method
OceanWolf Jun 13, 2015
81b9e69
Clean up the code a bit
OceanWolf Jun 13, 2015
85f0668
Remove old code from backend_managers
OceanWolf Jun 15, 2015
6535148
Cleanup
OceanWolf Jun 22, 2015
73e1122
Explicity get set manager as None if appropiate.
OceanWolf Jun 22, 2015
592c49b
figure attribute and canvas property
fariza Jun 22, 2015
b5d7f57
Fix FigureCanvasBase
OceanWolf Jun 23, 2015
b842bdc
super
OceanWolf Jun 25, 2015
92de15e
figure setter
fariza Jun 25, 2015
b619923
Improve MEP22 Tool Searching Structure
OceanWolf Jun 25, 2015
a07e482
adding example file
fariza Jun 25, 2015
2dd8895
super dooper
OceanWolf Jun 26, 2015
ce9c8e7
Revert old example and fix new one.
OceanWolf Jun 26, 2015
5542c5a
Improve MEP22 tool-searching method.
OceanWolf Jun 27, 2015
a975717
MEP22 Save Figure Tool
OceanWolf Jun 27, 2015
ecf1f23
pep8
OceanWolf Jun 27, 2015
4531085
Make ToolConfigureSubplots a generic tool
OceanWolf Jun 28, 2015
87fbd59
Improve flow handling and make it a lot more generic
OceanWolf Jun 28, 2015
f7eb33d
Missing resize method
OceanWolf Jun 28, 2015
0a2aa5c
Convert to new structure for finding tools
OceanWolf Jun 28, 2015
777b162
doc
OceanWolf Jun 29, 2015
468bdd7
Add ExpandableBase
OceanWolf Jun 29, 2015
209af6b
Template Backend plus fix FigManager for non-GUI backends and add gen…
OceanWolf Jun 29, 2015
06686c7
rcParam and Travis
OceanWolf Jul 19, 2015
2d93df8
test always MEP27
OceanWolf Jul 20, 2015
6b15982
Fix FigureManager to allow pyplot to work for non GUI backends
OceanWolf Jul 27, 2015
61f61f6
Fix Gcf.show_all()
OceanWolf Jul 27, 2015
71f4813
doc
OceanWolf Jul 27, 2015
d3064b6
pep8
OceanWolf Jul 27, 2015
2ca898c
remove show_popup
OceanWolf Jul 27, 2015
a567af6
AttributeError
OceanWolf Sep 22, 2015
09fc887
Fixes for MEP27
OceanWolf Aug 3, 2016
f60333d
STY: replace \ with () for line continuation
tacaswell Jun 19, 2017
072c47a
ENH: make MainLoopBase a context manager
tacaswell Jun 19, 2017
214b684
MNT: further simplify MainLoopBase
tacaswell Jun 25, 2017
35838c9
WIP:
tacaswell Jun 27, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ env:
- PYTEST_ARGS="-rawR --maxfail=1 --timeout=300 --durations=25 --cov-report= --cov=lib -n $NPROC"
- PYTHON_ARGS=
- DELETE_FONT_CACHE=
- USENEWTOOLMANAGER=false

matrix:
include:
Expand All @@ -59,7 +60,7 @@ matrix:
- python: 3.5
env: BUILD_DOCS=true
- python: 3.6
env: DELETE_FONT_CACHE=1 INSTALL_PEP8=pytest-pep8 RUN_PEP8=--pep8 PANDAS=pandas
env: DELETE_FONT_CACHE=1 INSTALL_PEP8=pytest-pep8 RUN_PEP8=--pep8 PANDAS=pandas USENEWTOOLMANAGER=true
- python: "nightly"
env: PRE=--pre
- os: osx
Expand Down Expand Up @@ -181,6 +182,9 @@ before_script:
export DISPLAY=:99.0
sh -e /etc/init.d/xvfb start
fi
if [[ $USENEWTOOLMANAGER == true ]]; then
cp .travis/toolmgr_matplotlibrc matplotlibrc
fi

script: ci/travis/test_script.sh

Expand Down
1 change: 1 addition & 0 deletions .travis/toolmgr_matplotlibrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
toolbar : toolmanager
35 changes: 18 additions & 17 deletions doc/devel/MEP/MEP27.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@

Status
======
**Discussion**
**Progress**

Branches and Pull requests
==========================
Main PR (including GTK3):

+ https://github.com/matplotlib/matplotlib/pull/4143

Backend specific branch diffs:

+ https://github.com/OceanWolf/matplotlib/compare/backend-refactor...OceanWolf:backend-refactor-tkagg
+ https://github.com/OceanWolf/matplotlib/compare/backend-refactor...OceanWolf:backend-refactor-qt
+ https://github.com/OceanWolf/matplotlib/compare/backend-refactor...backend-refactor-wx
Expand Down Expand Up @@ -79,15 +81,12 @@ The description of this MEP gives us most of the solution:
1. To remove the windowing aspect out of ``FigureManagerBase`` letting
it simply wrap this new class along with the other backend classes.
Create a new ``WindowBase`` class that can handle this
functionality, with pass-through methods (:arrow_right:) to
functionality, with pass-through methods (->) to
``WindowBase``. Classes that subclass ``WindowBase`` should also
subclass the GUI specific window class to ensure backward
compatibility (``manager.window == manager.window``).
2. Refactor the mainloop of ``ShowBase`` into ``MainLoopBase``, which
encapsulates the end of the loop as well. We give an instance of
``MainLoop`` to ``FigureManager`` as a key unlock the exit method
(requiring all keys returned before the loop can die). Note this
opens the possibility for multiple backends to run concurrently.
encapsulates the end of the loop as well.
3. Now that ``FigureManagerBase`` has no backend specifics in it, to
rename it to ``FigureManager``, and move to a new file
``backend_managers.py`` noting that:
Expand All @@ -103,30 +102,30 @@ The description of this MEP gives us most of the solution:
|FigureManagerBase(canvas, num) |FigureManager(figure, num) |``WindowBase(title)``|Notes |
| | | | |
+======================================+==============================+=====================+================================+
|show | |show | |
|show |-> |show | |
+--------------------------------------+------------------------------+---------------------+--------------------------------+
|destroy |calls destroy on all |destroy | |
| |components | | |
+--------------------------------------+------------------------------+---------------------+--------------------------------+
|full_screen_toggle |handles logic |set_fullscreen | |
+--------------------------------------+------------------------------+---------------------+--------------------------------+
|resize | |resize | |
|resize |-> |resize | |
+--------------------------------------+------------------------------+---------------------+--------------------------------+
|key_press |key_press | | |
|key_press |key_press |X | |
+--------------------------------------+------------------------------+---------------------+--------------------------------+
|show_popup |show_poup | |Not used anywhere in mpl, and |
|show_popup |X |X |Not used anywhere in mpl, and |
| | | |does nothing. |
+--------------------------------------+------------------------------+---------------------+--------------------------------+
|get_window_title | |get_window_title | |
|get_window_title |-> |get_window_title | |
+--------------------------------------+------------------------------+---------------------+--------------------------------+
|set_window_title | |set_window_title | |
|set_window_title |-> |set_window_title | |
+--------------------------------------+------------------------------+---------------------+--------------------------------+
| |_get_toolbar | |A common method to all |
|X |_get_toolbar |X |A common method to all |
| | | |subclasses of FigureManagerBase |
+--------------------------------------+------------------------------+---------------------+--------------------------------+
| | |set_default_size | |
|X |X |set_default_size | |
+--------------------------------------+------------------------------+---------------------+--------------------------------+
| | |add_element_to_window| |
|X |X |add_element | |
+--------------------------------------+------------------------------+---------------------+--------------------------------+


Expand All @@ -135,14 +134,14 @@ The description of this MEP gives us most of the solution:
+==========+============+=============+
|mainloop |begin | |
+----------+------------+-------------+
| |end |Gets called |
|X |end |Gets called |
| | |automagically|
| | |when no more |
| | |instances of |
| | |the subclass |
| | |exist |
+----------+------------+-------------+
|__call__ | |Method moved |
|__call__ |X |Method moved |
| | |to |
| | |Gcf.show_all |
+----------+------------+-------------+
Expand Down Expand Up @@ -191,6 +190,8 @@ in the same manner as everything else.
| | |window, so this also |
| | |breaks BC. |
+-------------------------+-------------------------+-------------------------+
|WebAgg |canvas | |
+-------------------------+-------------------------+-------------------------+


Alternatives
Expand Down
51 changes: 51 additions & 0 deletions examples/user_interfaces/gui_elements.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'''This example demonstrates how to:
* Create new toolbars
* Create new windows
Using `matplotlib.backend_managers.ToolManager`,
`matplotlib.backend_bases.WindowBase` and
`matplotlib.backend_bases.ToolContainerBase`
'''

from __future__ import print_function
import matplotlib
matplotlib.use('GTK3Cairo')
matplotlib.rcParams['toolbar'] = 'toolmanager'
import matplotlib.pyplot as plt

fig = plt.figure()

# Shortcuts to FigureManager and ToolManager
manager = fig.canvas.manager
tool_mgr = manager.toolmanager

# Create a new toolbar
topbar = manager.backend.Toolbar(tool_mgr)

# Add it to the figure window, we can place it north, east, west and south
manager.window.add_element(topbar, 'north')

# Remove some tools from the main toolbar and add them to the
# new sidebar
for tool in ('home', 'back', 'forward'):
manager.toolbar.remove_toolitem(tool)
topbar.add_tool(tool, None)

plt.plot([1, 2, 3])

# Add a new window
win = manager.backend.Window('Extra tools')

# create a sidebar for the new window
sidebar = manager.backend.Toolbar(tool_mgr)

# add the sidebar to the new window
win.add_element(sidebar, 'west')

# Add some tools to the new sidebar
for tool in ('home', 'back', 'forward', 'zoom', 'pan'):
sidebar.add_tool(tool, None)

# show the new window
win.show()

plt.show()
4 changes: 2 additions & 2 deletions examples/user_interfaces/toolmanager_sgskip.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def set_lines_visibility(self, state):

# Add the custom tools that we created
fig.canvas.manager.toolmanager.add_tool('List', ListTools)
fig.canvas.manager.toolmanager.add_tool('Show', GroupHideTool, gid='mygroup')
fig.canvas.manager.toolmanager.add_tool('Hide', GroupHideTool, gid='mygroup')


# Add an existing tool to new group `foo`.
Expand All @@ -93,6 +93,6 @@ def set_lines_visibility(self, state):

# To add a custom tool to the toolbar at specific location inside
# the navigation group
fig.canvas.manager.toolbar.add_tool('Show', 'navigation', 1)
fig.canvas.manager.toolbar.add_tool('Hide', 'navigation', 1)

plt.show()
59 changes: 57 additions & 2 deletions lib/matplotlib/_pylab_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import gc
import atexit

from matplotlib import is_interactive


def error_msg(msg):
print(msg, file=sys.stderr)
Expand All @@ -35,6 +37,16 @@ class Gcf(object):
_activeQue = []
figs = {}

@classmethod
def add_figure_manager(cls, manager):
cls.figs[manager.num] = manager
try: # TODO remove once all backends converted to use the new manager.
manager.mpl_connect('window_destroy_event', cls.destroy_cbk)
except:
pass

cls.set_active(manager)

@classmethod
def get_fig_manager(cls, num):
"""
Expand All @@ -46,6 +58,46 @@ def get_fig_manager(cls, num):
cls.set_active(manager)
return manager

@classmethod
def show_all(cls, block=None):
"""
Show all figures. If *block* is not None, then
it is a boolean that overrides all other factors
determining whether show blocks by calling mainloop().
The other factors are:
it does not block if run inside ipython's "%pylab" mode
it does not block in interactive mode.
"""

managers = cls.get_all_fig_managers()
if not managers:
return

# treat the first manager as proto-typical of all
m0 = managers[0]

if block is None:
# webagg always needs to block because tornado is
# not integrated into the REPL
block = (not is_interactive()) or m0.backend_name == 'webagg'

for manager in managers:
manager.show()

if block:
ml = m0.backend.MainLoop()
counter = {'open_windows': len(managers)}

def on_window_close(ev):
counter['open_windows'] -= 1
if counter['open_windows'] < 1:
ml.end()

for manager in managers:
manager.mpl_connect('window_destroy_event', on_window_close)

ml.begin()

@classmethod
def destroy(cls, num):
"""
Expand All @@ -68,7 +120,7 @@ def destroy(cls, num):
cls._activeQue.append(f)

del cls.figs[num]
manager.destroy()
manager.destroy() # Unneeded with MEP27 remove later
gc.collect(1)

@classmethod
Expand Down Expand Up @@ -137,7 +189,6 @@ def set_active(cls, manager):
if m != manager:
cls._activeQue.append(m)
cls._activeQue.append(manager)
cls.figs[manager.num] = manager

@classmethod
def draw_all(cls, force=False):
Expand All @@ -149,4 +200,8 @@ def draw_all(cls, force=False):
if force or f_mgr.canvas.figure.stale:
f_mgr.canvas.draw_idle()

@classmethod
def destroy_cbk(cls, event):
cls.destroy(event.figure_manager.num)

atexit.register(Gcf.destroy_all)
Loading