1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """Base class module for the user function GUI elements."""
25
26
27 from re import search
28 from string import split
29 import wx
30 from wx.lib import scrolledpanel
31
32
33 from prompt.base_class import _strip_lead
34 from status import Status; status = Status()
35
36
37 from gui.fonts import font
38 from gui.interpreter import Interpreter; interpreter = Interpreter()
39 from gui.misc import str_to_gui
40 from gui.wizard import Wiz_page, Wiz_window
41
42
44 """User function GUI element base class."""
45
47 """Set up the window.
48
49 @param parent: The parent window.
50 @type parent: wx.Window instance
51 """
52
53
54 self.parent = parent
55
56
57 - def create_wizard(self, size_x=600, size_y=400, name=None, uf_page=None, apply_button=True, return_page=False):
58 """Create and return the wizard window.
59
60 @keyword size_x: The width of the wizard.
61 @type size_x: int
62 @keyword size_y: The height of the wizard.
63 @type size_y: int
64 @keyword name: The name of the user function, such as 'deselect.all'.
65 @type name: str
66 @keyword uf_page: The user function page class.
67 @type uf_page: class
68 @keyword apply_button: A flag which if true will show the apply button for that page. This will be passed to the wizard's add_page() method.
69 @type apply_button: bool
70 @keyword return_page: A flag which if True will cause the user function page to be returned.
71 @type return_page: bool
72 @return: The wizard dialog (and wizard page if the return flag is given).
73 @rtype: gui.wizard.Wiz_window instance, wizard page instance
74 """
75
76
77 comps = split(name, '.')
78 if len(comps) == 2:
79 base = comps[0]
80 fn = comps[1]
81 else:
82 base = None
83 fn = comps[0]
84
85
86 wizard = Wiz_window(parent=self.parent, size_x=size_x, size_y=size_y, title=self.get_title(base=base, fn=fn))
87
88
89 page = uf_page(wizard)
90 wizard.add_page(page, apply_button=apply_button)
91
92
93 if return_page:
94 return wizard, page
95 else:
96 return wizard
97
98
100 """Get the title for the wizard window from the user function documentation.
101
102 @keyword base: The name of the user function base class, if it exists.
103 @type base: str
104 @keyword fn: The name of the function of the base class, or the user function itself if there is no base class.
105 @type fn: str
106 @return: The title for the window.
107 @rtype: GUI str
108 """
109
110
111 title = 'relax: '
112
113
114 if base:
115 title = "%s%s." % (title, base)
116
117
118 title = "%s%s" % (title, fn)
119
120
121 return str_to_gui(title)
122
123
124 -class UF_page(Wiz_page):
125 """User function specific pages for the wizards."""
126
127
128 uf_path = None
129
130 - def __init__(self, parent, sync=False):
131 """Set up the window.
132
133 @param parent: The parent class containing the GUI.
134 @type parent: class instance
135 @keyword sync: A flag which if True will call user functions via interpreter.apply and if False via interpreter.queue.
136 @type sync: bool
137 """
138
139
140 self.sync = sync
141
142
143 self.defaults = {}
144
145
146 wx.Yield()
147
148
149 wx.BeginBusyCursor()
150
151
152 uf_class = getattr(interpreter._instance._interpreter, self.uf_path[0])
153
154
155 if len(self.uf_path) == 1:
156 self.uf = uf_class
157 else:
158 self.uf = getattr(uf_class, self.uf_path[1])
159
160
161 if hasattr(self.uf, '_doc_title_short'):
162 self.title = self.uf._doc_title_short
163 else:
164 self.title = self.uf._doc_title
165
166
167 super(UF_page, self).__init__(parent)
168
169
170 if wx.IsBusy():
171 wx.EndBusyCursor()
172
173
175 """Format the text by stripping whitespace.
176
177 @param text: The text to strip.
178 @type text: str
179 @return: The stripped text.
180 @rtype: str
181 """
182
183
184 stripped_text = _strip_lead(text)
185
186
187 while True:
188 if stripped_text[0] == "\n":
189 stripped_text = stripped_text[1:]
190 else:
191 break
192
193
194 while True:
195 if stripped_text[-1] == "\n":
196 stripped_text = stripped_text[:-1]
197 else:
198 break
199
200
201 return stripped_text
202
203
204 - def add_desc(self, sizer, max_y=220):
205 """Add the description to the dialog.
206
207 @param sizer: A sizer object.
208 @type sizer: wx.Sizer instance
209 @keyword max_y: The maximum height, in number of pixels, for the description.
210 @type max_y: int
211 """
212
213
214 spacing = 5
215
216
217 sizer.AddSpacer(5)
218 sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 0)
219 sizer.AddSpacer(5)
220
221
222 panel = scrolledpanel.ScrolledPanel(self, -1, name="desc")
223
224
225 panel_sizer = wx.BoxSizer(wx.VERTICAL)
226
227
228 text_list = []
229
230
231 if hasattr(self.uf, '_doc_desc'):
232 for element, type in self.process_doc([self.uf._doc_title, self.uf._doc_desc]):
233 text_list.append([element, type])
234
235
236 if hasattr(self.uf, '_doc_additional'):
237 for i in range(len(self.uf._doc_additional)):
238 for element, type in self.process_doc(self.uf._doc_additional[i]):
239 text_list.append([element, type])
240
241
242 tot_x = 0
243 tot_y = 0
244 text_elements = []
245 i = 0
246 for text, type in text_list:
247
248 text_elements.append(wx.StaticText(panel, -1, text, style=wx.TE_MULTILINE))
249
250
251 if type == 'title':
252 text_elements[-1].SetFont(font.subtitle)
253 elif type == 'desc':
254 text_elements[-1].SetFont(font.normal)
255 elif type == 'table':
256 text_elements[-1].SetFont(font.modern_small)
257
258
259 text_elements[-1].Wrap(self._main_size - 20)
260
261
262 x, y = text_elements[-1].GetSizeTuple()
263 tot_x += x
264 tot_y += y
265
266
267 tot_y += spacing
268 if i != 0:
269 tot_y += spacing
270
271
272 i += 1
273
274
275 if tot_y > max_y-10:
276
277 panel.SetInitialSize((self._main_size, max_y))
278
279
280 else:
281
282 for i in range(len(text_elements)):
283 text_elements[i].Wrap(self._main_size)
284
285
286 panel.SetInitialSize((tot_x, tot_y))
287
288
289 for i in range(len(text_elements)):
290
291 if i != 0:
292 panel_sizer.AddSpacer(spacing)
293
294
295 panel_sizer.Add(text_elements[i], 0, wx.ALIGN_LEFT, 0)
296
297
298 if text_list[i][1] == 'title':
299 panel_sizer.AddSpacer(spacing)
300
301
302 panel.SetSizer(panel_sizer)
303 panel.SetAutoLayout(1)
304 panel.SetupScrolling(scroll_x=False, scroll_y=True)
305 sizer.Add(panel, 0, wx.ALL|wx.EXPAND)
306
307
308 sizer.AddSpacer(5)
309 sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 0)
310 sizer.AddSpacer(5)
311
312
313 - def execute(self, uf, *args, **kwds):
314 """Execute the user function, either asynchronously or synchronously.
315
316 @param uf: The user function as a string.
317 @type uf: str
318 @param args: The user function arguments.
319 @type args: any arguments
320 @param kwds: The user function keyword arguments.
321 @type kwds: any keyword arguments
322 """
323
324
325 if self.sync:
326 interpreter.apply(uf, *args, **kwds)
327
328
329 else:
330 interpreter.queue(uf, *args, **kwds)
331
332
333 - def process_doc(self, doc):
334 """Process the documentation list.
335
336 @param doc: The documentation in the form of a list of the title and description.
337 @type doc: list of str
338 """
339
340
341 yield doc[0], 'title'
342
343
344 docstring_lines = split(doc[1], "\n")
345
346
347 text = [""]
348 type = ['desc']
349 in_table = False
350
351
352 for line in docstring_lines:
353
354 if not in_table and search('___', line):
355 in_table = True
356 text.append("")
357 type.append("table")
358
359
360 text[-1] = "%s%s\n" % (text[-1], line)
361
362
363 if in_table and search('^\\|_', line):
364 in_table = False
365 text.append("")
366 type.append("desc")
367
368
369 for i in range(len(text)):
370 yield text[i], type[i]
371