myWin.py 8.86 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# ================= FILE HEADER ========================================
#
#   myplotlib v1.0.1,
#
#   @file      myWin.py
#   @author    Yori 'AGy' Fournier
#   @licence   CC-BY-SA
#
#   MyWin class: Overlay of matplotlib FigureManager
#   class. It allows a cleaner and more confortable
#   usage of windows.
#
#   @Class MyWin
#
#   @Constructor
#
20
21
22
23
24
25
#                fig:           the MyFig object that need to be drawn
#                show:          a flag to show the window just after
#                               creation. (default: True)
#                fignum:        number of both the Window and the Figure.
#                debug:         flag for debugging, more verbatile.
#                (kw)args:      user defined arguments and keywords.
26
27
28
#
#   @section Functions
#
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#            - _boundFigure_:   bound a figure to the window (priv.)
#
#            - _unboundFigure_: unbound a figure to the window (priv.)
#
#            - set_figure:      a clean way of setting a new figure
#                               to the window.
#
#            - refresh:         redraw the window
#                               - clean the figure
#                               - plot the figure
#                               - draw the canvas
#
#            - drawFigure:      draw a given figure on the window
#                               - set the figure of needed
#                               - refresh
#
#            - close:           close the window
#
47
48
49
50
51
52
53
#   @section History
#
#   v 1.0.1 - MyWin class for the myplotlib module.
#
# ======================================================================
#
# IMPORT ---------------------------------------------------------------
54
from myplotlib import INFO, SEVR, WARN, DBUG, SPCE
55
from myplotlib import rcParams
56
from myplotlib import _G_WINDOWS
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
from myplotlib import np

# For the various backends
from myplotlib import FigureManager, FigureCanvas
if rcParams['backend'] == u'WXAgg':
    try:
        from matplotlib.backends.backend_wx import _create_wx_app
        from matplotlib.backends.backend_wxagg import FigureFrameWxAgg
    except ImportError:
        print(SEVR + "Apparently backend_wx[agg] are missing.")
        exit(1)
elif rcParams['backend'] == u'TkAgg':
    try:
        from matplotlib.externals import six
        from matplotlib.externals.six.moves import tkinter as Tk
    except ImportError:
        print(SEVR + "Apparently backend_tkagg is missing.")
        exit(1)
75
76


77
# Class MyWin Overwriting the disgusting Matplotlib.FigureManager class
78
class MyWin(FigureManager):
79
80

    # CONSTRUCTOR ------------------------------------------------------
81
82
    def __init__(self, fig, show=True, *args, **kwargs):
        
83
        # set the dpi to 75 (correct value for screen)
84
85
86
        if(fig.dpi != 75.):
            fig.dpi = 75.
        
87
88
89
        # Get the debug value
        debug = kwargs.get('debug', False)
        
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
        # Get the user specified ID of the window or set it to 0
        if 'fignum' in kwargs.keys():
            num = kwargs['fignum']
            fignumSpecifiedByUser = True
        else:
            num = 0
            fignumSpecifiedByUser = False
        
        # if ID already used
        if(num in [(window.num) for window in _G_WINDOWS]):
            
            # if user specified fignum then close former window and create new one
            if(fignumSpecifiedByUser):
                if(debug):
                    print(DBUG + "The fignum you specified already exists, I'll close the former window")
                # Close the window with the specified number
                _G_WINDOWS[np.where([(window.num == num) for window in _G_WINDOWS])[0][0]].close()
            else:
                # If user didn't specified a fignum
                # increase ID until found a free one
                while(num in [(window.num) for window in _G_WINDOWS]):
                    num = num + 1

        # If debug print the ID of the window
        if(debug):
            print(DBUG + "You choosed num = " + str(num))
        
117
118
        # before creating anything verify that the fig is not already
        # bounded to another window
119
        if fig.boundedToWin:
120
            # if it is the case close the bounded window.
121
            win = _G_WINDOWS[np.where([(window.num == fig.keywords['fignum']) for window in _G_WINDOWS])[0][0]]
122
123
            win.close()
        
124
        # Call the ugly FigureManagerGTK class
125
        # (already wondering if this is not a mistake...)
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
        if rcParams['backend'] == u'GTKAgg':
            try:
                print(INFO + "GTKAgg")
                FigureManager.__init__(self, FigureCanvas(fig), num)
                # this will work if gtk is loaded not if wxPython is the current backend
            except:
                print(SEVR + "Problem with GTKAgg")
        elif rcParams['backend'] == u'WXAgg':
            try:
                print(INFO + "WXAgg")
                # Yes it is ugly! Not my fault.
                _create_wx_app()
                frame = FigureFrameWxAgg(num, fig)
                FigureManager.__init__(self, frame.canvas, num, frame)
                self.frame.figmgr = self
            except:
                print(SEVR + "Problem with WXAgg")
        elif rcParams['backend'] == u'TkAgg':
            try:
                print(INFO + "TkAgg")
                window = Tk.Tk()
                window.withdraw()
                canvas = FigureCanvas(fig, master=window)
                FigureManager.__init__(self, canvas, num, window)
            except:
                print(SEVR + "Problem with TkAgg")
                
153
        # bound the figure to the window
154
155
156
        self.canvas.figure.boundedToWin = True
        self.canvas.figure.keywords['fignum'] = num
        
157
158
159
        # add the window in the global variable _G_WINDOWS
        # this guarenty that you never loose a window
        # (see myTool.py getWindow(num))
160
        _G_WINDOWS.append(self)
161
162
        
        # if show is on, then show the window
163
        if show:
164
165
166
167
168
169
170
171
172
173
            if rcParams['backend'] in (u'GTKAgg', u'TkAgg'):
                # For GTKAgg and TKAgg ---------------------------------
                self.refresh()
                self.show()
            elif rcParams['backend'] == u'WXAgg':
                # For WXAgg --------------------------------------------
                self.canvas.figure.clf()
                self.canvas.figure.plot()
                self.show()
                self.canvas.draw()
174
    
175
176
    
    # BOUND ------------------------------------------------------------
177
178
179
180
181
182
183
    def _boundFigure_(self, fig):
        
        fig.canvas = self.canvas
        self.canvas.figure = fig
        self.canvas.figure.boundedToWin = True
        self.canvas.figure.keywords['fignum'] = self.num
    
184
185
    
    # UNBOUND ----------------------------------------------------------
186
187
188
189
190
    def _unboundFigure_(self):
        
        self.canvas.figure.boundedToWin = False
        self.canvas.figure.keywords['fignum'] = -1
    
191
192
193
    
    # SETTERS ----------------------------------------------------------
    # SET FIGURE -------------------------------------------------------
194
195
    def set_figure(self, fig):
        
196
        # first unbound the former figure
197
198
        self._unboundFigure_()
        
199
200
        # if the new figure is already bounded close
        # its former container.
201
        if fig.boundedToWin:
202
            win = _G_WINDOWS[np.where([(window.num == fig.keywords['fignum']) for window in _G_WINDOWS])[0][0]]
203
            win.close()
204
205
        
        # bound the new figure
206
207
        self._boundFigure_(fig)
    
208
209
    
    # REFRESH ----------------------------------------------------------
210
    def refresh(self):
211
212
213
214
215
216
217
218
219
220
221
222
223

        if rcParams['backend'] in (u'GTKAgg', u'TkAgg'):
            # For GTKAgg and TKAgg ---------------------------------
            self.canvas.figure.clf()
            self.canvas.figure.plot()
            self.canvas.draw()
        elif rcParams['backend'] == u'WXAgg':
            # For WXAgg --------------------------------------------
            self.canvas.figure.clf()
            self.canvas.figure.plot()
            self.canvas.draw()
            self.canvas.figure.plot()
            self.canvas.draw()
224
    
225
226
    
    # DRAW -------------------------------------------------------------
227
    def drawFigure(self, fig):
228
229
        
        # if the figure is not the current one
230
        if(fig.keywords['fignum'] != self.num):
231
            # cleanly set the new figure
232
233
            self.set_figure(fig)
        
234
        # and refresh
235
236
        self.refresh()
    
237
238
    
    # CLOSE ------------------------------------------------------------
239
240
241
242
    def close(self):
        
        self._unboundFigure_()
        self.destroy()
243
        del _G_WINDOWS[np.where([(window == self) for window in _G_WINDOWS])[0][0]]
244
245
246
247
248
        # remark if you create the window like:
        # win = MyWin(fig)
        # then win is still refering the self
        # and therefore not yet freed
        # del win would free it entirely.