1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """Module containing the special objects for auto-generating the GUI user functions and classes."""
25
26
27 from re import search
28 from string import split
29 import wx
30 from wx.lib import scrolledpanel
31
32
33 import arg_check
34 from graphics import fetch_icon
35 from relax_errors import AllRelaxErrors, RelaxError
36 from relax_string import strip_lead
37 from status import Status; status = Status()
38 from user_functions.data import Uf_info; uf_info = Uf_info()
39 from user_functions.data import Uf_tables; uf_tables = Uf_tables()
40
41
42 from gui.components.free_file_format import Free_file_format
43 from gui.components.menu import build_menu_item
44 from gui.errors import gui_raise
45 from gui.fonts import font
46 from gui.input_elements.bool import Selector_bool
47 from gui.input_elements.dir import Selector_dir
48 from gui.input_elements.file import Selector_file
49 from gui.input_elements.sequence import Sequence
50 from gui.input_elements.sequence_2D import Sequence_2D
51 from gui.input_elements.spin_id import Spin_id
52 from gui.input_elements.value import Value
53 from gui.interpreter import Interpreter; interpreter = Interpreter()
54 from gui.misc import format_table
55 from gui.wizard import Wiz_page, Wiz_window
56
57
59 """Auto-generate the user function sub-menu.
60
61 @keyword parent: The parent window to bind the events to.
62 @type parent: wx instance
63 @keyword menubar: The menubar to attach the user function menus to.
64 @type menubar: wx.MenuBar instance
65 @return: The menu ID.
66 @rtype: int
67 """
68
69
70 menu1 = wx.Menu()
71 menu2 = wx.Menu()
72
73
74 pattern = '^[a-m]'
75
76
77 class_list = []
78 uf_store = Uf_storage()
79
80
81 class_item = None
82 menu = menu1
83 menu_index = 0
84 for name, data in uf_info.uf_loop():
85
86 if search('\.', name):
87 class_name, uf_name = split(name, '.')
88 else:
89 class_name = None
90
91
92 if class_name:
93 if class_name not in class_list:
94
95 if class_item != None:
96 menu.AppendItem(class_item)
97
98
99 class_data = uf_info.get_class(class_name)
100
101
102 class_id = wx.NewId()
103
104
105 class_item = build_menu_item(menu, id=class_id, text=class_data.menu_text, icon=fetch_icon(class_data.gui_icon, size='16x16'))
106
107
108 sub_menu = wx.Menu()
109 class_item.SetSubMenu(sub_menu)
110
111
112 class_list.append(class_name)
113
114
115 uf_id = wx.NewId()
116 sub_menu.AppendItem(build_menu_item(sub_menu, id=uf_id, text=data.menu_text, icon=fetch_icon(data.gui_icon, size='16x16')))
117
118
119 else:
120
121 if class_item != None:
122 menu.AppendItem(class_item)
123 class_item = None
124
125
126 uf_id = wx.NewId()
127 menu.AppendItem(build_menu_item(menu, id=uf_id, text=data.menu_text, icon=fetch_icon(data.gui_icon, size='16x16')))
128
129
130 if menu_index == 0 and not search(pattern, name):
131 menu = menu2
132 menu_index = 1
133
134
135 parent.Bind(wx.EVT_MENU, uf_store[name], id=uf_id)
136
137
138 if class_item != None:
139 menu.AppendItem(class_item)
140
141
142 title1 = "&User functions (a-m)"
143 title2 = "&User functions (n-z)"
144 menubar.Append(menu1, title1)
145 menubar.Append(menu2, title2)
146
147
148 return [menubar.FindMenu(title1), menubar.FindMenu(title2)]
149
150
151
153 """A special user function arg element which always returns True."""
154
156 """Initialise the object."""
157
158
159 self._value = True
160
161
163 """Simple method for returning the internal value."""
164
165
166 return self._value
167
168
170 """Internally store the value being set."""
171
172
173 self._value = value
174
175
176
178 """The object for auto-generating the GUI user functions."""
179
180 - def __call__(self, event=None, wx_parent=None, wx_wizard_sync=None, wx_wizard_run=True, wx_wizard_modal=False, **kwds):
181 """Make the GUI user function executable.
182
183 All keyword args, apart from 'event', 'wx_parent' and 'wx_wizard_run' will be assumed to be user function arguments and the Uf_page.SetValue() method of the page will be used to set the GUI arg elements to the values supplied.
184
185
186 @keyword event: The wx event.
187 @type event: wx event or None
188 @keyword wx_parent: The parent wx object to associate the user function wizard to.
189 @type wx_parent: wx object
190 @keyword wx_wizard_sync: A flag which if given will switch between synchronous and asynchronous user function operation.
191 @type wx_wizard_sync: None or bool
192 @keyword wx_wizard_run: A flag which if True will call the wizard run() method.
193 @type wx_wizard_run: bool
194 @keyword wx_wizard_modal: A flag which if True will cause the wizard run() method to have the modal flag set so that the wizard is modal.
195 @type wx_wizard_modal: bool
196 @return: The status of the call. If the call failed, False will be returned.
197 @rtype: bool
198 """
199
200
201 if wx_wizard_sync != None:
202 self._sync = wx_wizard_sync
203
204
205 if self.wizard == None or (wx_parent != None and wx_parent != self.wizard.GetParent()) or self.wizard._pages[0] == None:
206 status = self.create_wizard(wx_parent)
207 if not status:
208 return False
209
210
211 else:
212 self.wizard.reset()
213
214
215 if not self.page.update_args():
216 return False
217
218
219 for key in kwds:
220 self.page.SetValue(key, kwds[key])
221
222
223 if wx_wizard_run:
224 self.wizard.run(modal=wx_wizard_modal)
225
226
227 - def __init__(self, name, title=None, size=None, height_desc=None, apply_button=True, sync=False):
228 """Set up the object.
229
230 @param name: The name of the user function.
231 @type name: str
232 @keyword title: The long title of the user function to set as the window title.
233 @type title: str
234 @keyword size: The window size.
235 @type size: tuple of int
236 @keyword height_desc: The height in pixels of the description part of the wizard.
237 @type height_desc: int or None
238 @keyword apply_button: A flag specifying if the apply button should be shown or not. This defaults to True.
239 @type apply_button: bool
240 @keyword sync: A flag which if True will call user functions via interpreter.apply and if False via interpreter.queue.
241 @type sync: bool
242 """
243
244
245 self._name = name
246 self._title = title
247 self._size = size
248 self._height_desc = height_desc
249 self._apply_button = apply_button
250 self._sync = sync
251
252
253 self.wizard = None
254
255
256 - def create_page(self, wizard=None, sync=False):
257 """Create the user function wizard page GUI object.
258
259 @keyword wizard: The parent wizard.
260 @type wizard: Wiz_window instance
261 @keyword sync: A flag which if True will call user functions via interpreter.apply and if False via interpreter.queue.
262 @type sync: bool
263 @return: The user function page object.
264 @rtype: Uf_page instance
265 """
266
267
268 return Uf_page(self._name, parent=wizard, height_desc=self._height_desc, sync=self._sync)
269
270
272 """Create the user function wizard GUI object, with embedded wizard page.
273
274 @keyword parent: The parent wx window.
275 @type parent: wx.Window instance
276 @return: True if the wizard was created, False if a problem was encountered.
277 @rtype: bool
278 """
279
280
281 if parent == None:
282 app = wx.GetApp()
283 parent = app.gui
284
285
286 self.wizard = Wiz_window(parent=parent, size_x=self._size[0], size_y=self._size[1], title=self._title)
287
288
289 self.page = self.create_page(self.wizard, sync=self._sync)
290
291
292 if not self.page.update_args():
293 return False
294
295
296 self.wizard.add_page(self.page, apply_button=self._apply_button)
297
298
299 return True
300
301
302
303 -class Uf_page(Wiz_page):
304 """User function specific pages for the wizards."""
305
306 - def __init__(self, name, parent=None, height_desc=220, sync=False):
307 """Set up the window.
308
309 @param name: The name of the user function.
310 @type name: str
311 @keyword parent: The parent class containing the GUI.
312 @type parent: class instance
313 @keyword height_desc: The height in pixels of the description part of the wizard.
314 @type height_desc: int or None
315 @keyword sync: A flag which if True will call user functions via interpreter.apply and if False via interpreter.queue.
316 @type sync: bool
317 """
318
319
320 self.name = name
321 self.sync = sync
322
323
324 self.uf_args = {}
325
326
327 wx.Yield()
328
329
330 wx.BeginBusyCursor()
331
332
333 self.uf_data = uf_info.get_uf(name)
334
335
336 self.image_path = self.uf_data.wizard_image
337
338
339 if self.uf_data.title_short != None:
340 self.title = self.uf_data.title_short
341 else:
342 self.title = self.uf_data.title
343
344
345 super(Uf_page, self).__init__(parent, height_desc=height_desc)
346
347
348 if wx.IsBusy():
349 wx.EndBusyCursor()
350
351
353 """Format the text by stripping whitespace.
354
355 @param text: The text to strip.
356 @type text: str
357 @return: The stripped text.
358 @rtype: str
359 """
360
361
362 stripped_text = strip_lead(text)
363
364
365 while True:
366 if stripped_text[0] == "\n":
367 stripped_text = stripped_text[1:]
368 else:
369 break
370
371
372 while True:
373 if stripped_text[-1] == "\n":
374 stripped_text = stripped_text[:-1]
375 else:
376 break
377
378
379 return stripped_text
380
381
382 - def _intro_text(self, keys, values, prompt=True):
383 """Build and return the user function intro text.
384
385 @param keys: The user function keys.
386 @type keys: list of str
387 @param values: The values corresponding to the keys.
388 @type values: list
389 @keyword prompt: A flag which if True will cause the prompt text to be included.
390 @type prompt: bool
391 @return: The user function intro text.
392 @rtype: str
393 """
394
395
396 text = ""
397
398
399 if prompt:
400 text += status.ps3
401
402
403 text += "%s(" % self.name
404
405
406 for i in range(len(keys)):
407
408 if i >= 1:
409 text += ", "
410
411
412 text += "%s=%s" % (keys[i], repr(values[i]))
413
414
415 text += ")"
416
417
418 return text
419
420
421 - def Clear(self, key):
422 """Special wizard method for clearing the value of the GUI element corresponding to the key.
423
424 @param key: The key corresponding to the desired GUI element.
425 @type key: str
426 """
427
428
429 self.uf_args[key].Clear()
430
431
432 - def GetValue(self, key):
433 """Special wizard method for getting the value of the GUI element corresponding to the key.
434
435 @param key: The key corresponding to the desired GUI element.
436 @type key: str
437 @return: The value that the specific GUI element's GetValue() method returns.
438 @rtype: unknown
439 """
440
441
442 if key not in self.uf_args.keys():
443 return None
444
445
446 return self.uf_args[key].GetValue()
447
448
449 - def SetValue(self, key, value):
450 """Special wizard method for setting the value of the GUI element corresponding to the key.
451
452 @param key: The key corresponding to the desired GUI element.
453 @type key: str
454 @param value: The value that the specific GUI element's SetValue() method expects.
455 @type value: unknown
456 """
457
458
459 arg = None
460 for i in range(len(self.uf_data.kargs)):
461 if self.uf_data.kargs[i]['name'] == key:
462 arg = self.uf_data.kargs[i]
463
464
465 if arg == None:
466 raise RelaxError("The key '%s' is unknown." % key)
467
468
469 if 'free_file_format' in self.uf_args and key in ['spin_id_col', 'mol_name_col', 'res_num_col', 'res_name_col', 'spin_num_col', 'spin_name_col', 'data_col', 'error_col', 'sep']:
470 self.uf_args['free_file_format'].SetValue(key, value)
471
472
473 elif arg['arg_type'] in ['func', 'func args']:
474 pass
475
476
477 else:
478 self.uf_args[key].SetValue(value)
479
480
481 - def UpdateChoices(self, key, combo_choices=None, combo_data=None, combo_default=None):
482 """Special user function page method for updating the list of choices in a ComboBox type element.
483
484 @param key: The key corresponding to the desired GUI element.
485 @type key: str
486 @keyword combo_choices: The list of choices to present to the user. This is only used if the element_type is set to 'combo'.
487 @type combo_choices: list of str
488 @keyword combo_data: The data returned by a call to GetValue(). This is only used if the element_type is set to 'combo'. If supplied, it should be the same length at the combo_choices list. If not supplied, the combo_choices list will be used for the returned data.
489 @type combo_data: list
490 @keyword combo_default: The default value of the ComboBox. This is only used if the element_type is set to 'combo'.
491 @type combo_default: str or None
492 """
493
494
495 self.uf_args[key].UpdateChoices(combo_choices=combo_choices, combo_data=combo_data, combo_default=combo_default)
496
497
498 - def add_contents(self, sizer):
499 """Add the specific GUI elements.
500
501 @param sizer: A sizer object.
502 @type sizer: wx.Sizer instance
503 """
504
505
506 free_format = False
507 free_format_data = False
508
509
510 for i in range(len(self.uf_data.kargs)):
511
512 arg = self.uf_data.kargs[i]
513
514
515 desc = "The %s:" % arg['desc_short']
516
517
518 if arg['arg_type'] == 'file sel':
519 self.uf_args[arg['name']] = Selector_file(name=arg['name'], parent=self, default=arg['default'], sizer=sizer, desc=desc, wildcard=arg['wiz_filesel_wildcard'], style=arg['wiz_filesel_style'], tooltip=arg['desc'], divider=self._div_left, height_element=self.height_element, read_only=arg['wiz_read_only'])
520
521
522 elif arg['arg_type'] == 'dir':
523 pass
524
525
526 elif arg['arg_type'] == 'dir sel':
527 self.uf_args[arg['name']] = Selector_dir(name=arg['name'], parent=self, default=arg['default'], sizer=sizer, desc=desc, style=arg['wiz_dirsel_style'], tooltip=arg['desc'], divider=self._div_left, height_element=self.height_element, read_only=arg['wiz_read_only'])
528
529
530 elif arg['arg_type'] == 'free format':
531
532 free_format = True
533 if arg['name'] == 'data_col':
534 free_format_data = True
535
536
537 elif arg['arg_type'] in ['func', 'func args']:
538 pass
539
540
541 elif arg['arg_type'] in ['force flag']:
542 self.uf_args[arg['name']] = Force_true()
543
544
545 elif arg['arg_type'] in ['spin ID']:
546 self.uf_args[arg['name']] = Spin_id(name=arg['name'], parent=self, default=arg['default'], element_type=arg['wiz_element_type'], sizer=sizer, desc=desc, combo_choices=arg['wiz_combo_choices'], combo_data=arg['wiz_combo_data'], tooltip=arg['desc'], divider=self._div_left, height_element=self.height_element, can_be_none=arg['can_be_none'])
547
548
549 elif arg['py_type'] in ['float', 'int', 'num', 'str']:
550 self.uf_args[arg['name']] = Value(name=arg['name'], parent=self, default=arg['default'], element_type=arg['wiz_element_type'], value_type=arg['py_type'], min=arg['min'], max=arg['max'], sizer=sizer, desc=desc, combo_choices=arg['wiz_combo_choices'], combo_data=arg['wiz_combo_data'], tooltip=arg['desc'], divider=self._div_left, height_element=self.height_element, read_only=arg['wiz_read_only'], can_be_none=arg['can_be_none'])
551
552
553 elif arg['py_type'] == 'bool':
554 self.uf_args[arg['name']] = Selector_bool(name=arg['name'], parent=self, element_type=arg['wiz_element_type'], sizer=sizer, desc=desc, tooltip=arg['desc'], default=arg['default'], divider=self._div_left, height_element=self.height_element)
555
556
557 elif arg['py_type'] in ['float_list', 'int_list', 'num_list', 'str_list', 'float_tuple', 'int_tuple', 'num_tuple', 'str_tuple', 'float_array', 'int_array', 'float_or_float_list', 'int_or_int_list', 'num_or_num_list', 'str_or_str_list', 'float_or_float_tuple', 'int_or_int_tuple', 'num_or_num_tuple', 'str_or_str_tuple', 'val_or_list']:
558
559 if arg['py_type'] in ['float_list', 'int_list', 'num_list', 'str_list', 'float_array', 'int_array', 'float_or_float_list', 'int_or_int_list', 'num_or_num_list', 'str_or_str_list', 'val_or_list']:
560 seq_type = 'list'
561 else:
562 seq_type = 'tuple'
563
564
565 if arg['py_type'] in ['float_list', 'num_list', 'float_tuple', 'num_tuple', 'float_array', 'float_or_float_list', 'num_or_num_list', 'float_or_float_tuple', 'num_or_num_tuple']:
566 value_type = 'float'
567 elif arg['py_type'] in ['int_list', 'int_tuple', 'int_array', 'int_or_int_list', 'int_or_int_tuple']:
568 value_type = 'int'
569 elif arg['py_type'] in ['str_list', 'str_tuple', 'str_array', 'str_or_str_list', 'str_or_str_tuple']:
570 value_type = 'str'
571 else:
572 value_type = None
573
574
575 single_value = False
576 if arg['py_type'] in ['float_or_float_list', 'int_or_int_list', 'num_or_num_list', 'str_or_str_list', 'float_or_float_tuple', 'int_or_int_tuple', 'num_or_num_tuple', 'str_or_str_tuple', 'val_or_list']:
577 single_value = True
578
579
580 dim = None
581 if isinstance(arg['dim'], int):
582 dim = arg['dim']
583
584 self.uf_args[arg['name']] = Sequence(name=arg['name'], parent=self, default=arg['default'], element_type=arg['wiz_element_type'], seq_type=seq_type, value_type=value_type, dim=dim, min=arg['min'], max=arg['max'], sizer=sizer, desc=desc, combo_choices=arg['wiz_combo_choices'], combo_data=arg['wiz_combo_data'], combo_list_min=arg['wiz_combo_list_min'], tooltip=arg['desc'], single_value=single_value, divider=self._div_left, height_element=self.height_element, read_only=arg['wiz_read_only'], can_be_none=arg['can_be_none'])
585
586
587 elif arg['py_type'] in ['float_list_of_lists', 'int_list_of_lists', 'num_list_of_lists', 'str_list_of_lists', 'float_tuple_of_tuples', 'int_tuple_of_tuples', 'num_tuple_of_tuples', 'str_tuple_of_tuples', 'float_matrix', 'int_matrix']:
588
589 if arg['py_type'] in ['float_list_of_lists', 'int_list_of_lists', 'num_list_of_lists', 'str_list_of_lists', 'float_matrix', 'int_matrix']:
590 seq_type = 'list'
591 else:
592 seq_type = 'tuple'
593
594
595 if arg['py_type'] in ['float_list_of_lists', 'float_tuple_of_tuples', 'num_list_of_lists', 'num_tuple_of_tuples', 'float_matrix']:
596 value_type = 'float'
597 elif arg['py_type'] in ['int_list_of_lists', 'int_tuple_of_tuples', 'int_matrix']:
598 value_type = 'int'
599 else:
600 value_type = 'str'
601
602 self.uf_args[arg['name']] = Sequence_2D(name=arg['name'], parent=self, default=arg['default'], sizer=sizer, element_type=arg['wiz_element_type'], seq_type=seq_type, value_type=value_type, dim=arg['dim'], min=arg['min'], max=arg['max'], titles=arg['list_titles'], desc=desc, combo_choices=arg['wiz_combo_choices'], combo_data=arg['wiz_combo_data'], combo_list_min=arg['wiz_combo_list_min'], tooltip=arg['desc'], divider=self._div_left, height_element=self.height_element, read_only=arg['wiz_read_only'], can_be_none=arg['can_be_none'])
603
604
605 else:
606 raise RelaxError("The Python object type '%s' cannot be handled." % arg['py_type'])
607
608
609 if free_format:
610 self.uf_args['free_file_format'] = Free_file_format(sizer, parent=self, data_cols=free_format_data, padding=3, spacer=0)
611
612
613 - def add_desc(self, sizer, max_y=220):
614 """Add the description to the dialog.
615
616 @param sizer: A sizer object.
617 @type sizer: wx.Sizer instance
618 @keyword max_y: The maximum height, in number of pixels, for the description.
619 @type max_y: int
620 """
621
622
623 spacing = 15
624
625
626 sizer.AddSpacer(5)
627 sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 0)
628 sizer.AddSpacer(5)
629
630
631 panel = scrolledpanel.ScrolledPanel(self, -1, name="desc")
632
633
634 panel_sizer = wx.BoxSizer(wx.VERTICAL)
635
636
637 tot_y = 0
638 text_elements = []
639 text_types = []
640
641
642 name = "The %s user function" % self.name
643 text = wx.StaticText(panel, -1, name, style=wx.TE_MULTILINE)
644 text.SetFont(font.subtitle)
645 text_elements.append(text)
646 text_types.append('title')
647
648
649 x, y = text.GetSizeTuple()
650 tot_y += y
651 tot_y += spacing
652
653
654 if self.uf_data.title:
655
656 text = wx.StaticText(panel, -1, self.uf_data.title, style=wx.TE_MULTILINE)
657
658
659 text.SetFont(font.normal_italic)
660
661
662 x, y = text.GetSizeTuple()
663 tot_y += y
664
665
666 tot_y += spacing
667
668
669 text_elements.append(text)
670 text_types.append('synopsis')
671
672
673 if self.uf_data.desc != None:
674
675 for i in range(len(self.uf_data.desc)):
676
677 desc = self.uf_data.desc[i]
678
679
680 if desc.get_title() == 'Prompt examples':
681 continue
682
683
684 for type, element in desc.element_loop(title=True):
685
686 text = ''
687 if isinstance(element, str):
688 text = element
689
690
691 if type == 'table':
692 text = format_table(uf_tables.get_table(element))
693
694
695 elif type == 'list':
696
697 for j in range(len(element)):
698 text += " - %s\n" % element[j]
699
700
701 elif type == 'item list':
702
703 for j in range(len(element)):
704
705 if element[j][0] in [None, '']:
706 text += " %s\n" % element[j][1]
707 else:
708 text += " %s: %s\n" % (element[j][0], element[j][1])
709
710
711 text_obj = wx.StaticText(panel, -1, text, style=wx.TE_MULTILINE)
712
713
714 if type == 'title':
715 text_obj.SetFont(font.subtitle)
716 elif type == 'paragraph':
717 text_obj.SetFont(font.normal)
718 elif type in ['table', 'verbatim']:
719 text_obj.SetFont(font.modern_small)
720 else:
721 text_obj.SetFont(font.normal)
722
723
724 if type in ['paragraph', 'list', 'item list']:
725 text_obj.Wrap(self._main_size - 20)
726
727
728 x, y = text_obj.GetSizeTuple()
729 tot_y += y
730
731
732 tot_y += spacing
733
734
735 if i != 0 and type == 'title':
736 tot_y += spacing
737
738
739 text_elements.append(text_obj)
740 text_types.append(type)
741
742
743 tot_y -= spacing
744 tot_y += 20
745
746
747 if tot_y > max_y:
748 panel.SetInitialSize((self._main_size, max_y))
749
750
751 else:
752 panel.SetInitialSize((self._main_size, tot_y))
753
754
755 n = len(text_elements)
756 for i in range(n):
757
758 if i > 1 and text_types[i] == 'title':
759 panel_sizer.AddSpacer(spacing)
760
761
762 panel_sizer.Add(text_elements[i], 0, wx.ALIGN_LEFT, 0)
763
764
765 if i != n - 1:
766 panel_sizer.AddSpacer(spacing)
767
768
769 panel.SetSizer(panel_sizer)
770 panel.SetAutoLayout(1)
771 panel.SetupScrolling(scroll_x=False, scroll_y=True)
772 sizer.Add(panel, 0, wx.ALL|wx.EXPAND)
773
774
775 sizer.AddSpacer(5)
776 sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 0)
777 sizer.AddSpacer(5)
778
779
780 - def execute(self, uf, *args, **kwds):
781 """Execute the user function, either asynchronously or synchronously.
782
783 @param uf: The user function as a string.
784 @type uf: str
785 @param args: The user function arguments.
786 @type args: any arguments
787 @param kwds: The user function keyword arguments.
788 @type kwds: any keyword arguments
789 """
790
791
792 if self.sync or status.gui_uf_force_sync:
793 interpreter.apply(uf, *args, **kwds)
794
795
796 else:
797 interpreter.queue(uf, *args, **kwds)
798
799
801 """Remove this page from the observers."""
802
803
804 status.observers.gui_uf.unregister(self.name)
805
806
807 - def on_display(self):
808 """Clear and update the data if needed."""
809
810
811 status.observers.gui_uf.register(self.name, self.update_args)
812
813
814 return self.update_args()
815
816
817 - def on_execute(self):
818 """Execute the user function."""
819
820
821 kargs = {}
822 for i in range(len(self.uf_data.kargs)):
823
824 name = self.uf_data.kargs[i]['name']
825
826
827 kargs[name] = self.GetValue(name)
828
829
830 if self.uf_data.kargs[i]['wiz_combo_list_min'] != None and kargs[name] == None:
831 return
832
833
834 if 'free_file_format' in self.uf_args:
835 kargs.update(self.uf_args['free_file_format'].GetValue())
836
837
838 if self.uf_data.display:
839
840 app = wx.GetApp()
841
842
843 app.gui.show_controller(None)
844
845
846 app.gui.controller.log_panel.on_goto_end(None)
847
848
849 if status.uf_intro:
850
851 keys = []
852 values = []
853 for i in range(len(self.uf_data.kargs)):
854 keys.append(self.uf_data.kargs[i]['name'])
855 values.append(kargs[self.uf_data.kargs[i]['name']])
856
857
858 print(self._intro_text(keys, values))
859
860
861 self.execute(self.name, **kargs)
862
863
864 if status.show_gui and self.uf_data.display:
865 wx.CallAfter(app.gui.controller.Raise)
866
867
869 """Remove this page from the observers."""
870
871
872 status.observers.gui_uf.unregister(self.name)
873
874
875 - def update_args(self):
876 """Update all the argument ComboBox choices.
877
878 @return: The status of the update - False if a RelaxError occurs, True otherwise.
879 @rtype: bool
880 """
881
882
883 for i in range(len(self.uf_data.kargs)):
884
885 name = self.uf_data.kargs[i]['name']
886
887
888 iterator = self.uf_data.kargs[i]['wiz_combo_iter']
889 if iterator == None:
890 continue
891
892
893 try:
894 choices = []
895 data = []
896 for vals in iterator():
897 if arg_check.is_tuple(vals, size=2, raise_error=False):
898 choices.append(vals[0])
899 data.append(vals[1])
900 else:
901 choices.append(vals)
902 data.append(vals)
903
904
905 except AllRelaxErrors, instance:
906
907 self.setup_fail = True
908
909
910 gui_raise(instance)
911
912
913 return False
914
915
916 val = self.uf_args[name].GetValue()
917
918
919 self.UpdateChoices(name, combo_choices=choices, combo_data=data, combo_default=val)
920
921
922 return True
923
924
925
927 """A singleton container for holding all the GUI user functions."""
928
929
930 _instance = None
931
932 - def __new__(self, *args, **kargs):
955