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 wizard GUI elements."""
25
26
27 import wx
28 from wx.lib import buttons, scrolledpanel
29
30
31 from data import Relax_data_store; ds = Relax_data_store()
32 from generic_fns.mol_res_spin import id_string_doc
33 from relax_errors import RelaxImplementError
34 from status import Status; status = Status()
35
36
37 from gui.interpreter import Interpreter; interpreter = Interpreter()
38 from gui.filedialog import RelaxFileDialog
39 from gui.fonts import font
40 from gui.icons import relax_icons
41 from gui.misc import add_border, bool_to_gui, gui_to_int, gui_to_str, int_to_gui, open_file, protected_exec, str_to_gui
42 from gui.message import Question
43 from gui import paths
44 from gui.wizard_elements import Integer, String, String_list, String_list_of_lists
45
46
47 -class Wiz_page(wx.Panel):
48 """The wizard pages to be placed inside the wizard.
49
50 To inherit from this class, you must minimally supply the add_contents() method. This method should build the specific GUI elements. The following methods are also designed to be overwritten:
51
52 - add_artwork(), this builds the left hand artwork section of the page.
53 - add_contents(), this builds the right hand section of the page.
54 - on_display(), this is executed when the page is displayed.
55 - on_display_post(), this is executed when the page is displayed, directly after the on_display method.
56 - on_execute(), this is executed when the wizard is terminated or the apply button is hit.
57 - on_next(), this is executed when moving to the next wizard page.
58
59 The following methods can be used by add_contents() to create standard GUI elements:
60
61 - chooser()
62 - combo_box()
63 - file_selection()
64 - free_file_format()
65 - input_field()
66 - text()
67
68 These are described in full detail in their docstrings.
69 """
70
71
72 art_spacing = 20
73 divider = None
74 height_desc = 220
75 height_element = 27
76 image_path = paths.IMAGE_PATH + "relax.gif"
77 main_text = ''
78 setup_fail = False
79 size_button = (100, 33)
80 size_square_button = (33, 33)
81 title = ''
82
83 - def __init__(self, parent):
84 """Set up the window.
85
86 @param parent: The parent GUI element.
87 @type parent: wx.object instance
88 """
89
90
91 self.parent = parent
92
93
94 wx.Panel.__init__(self, parent, id=-1)
95
96
97 self.exec_status = False
98
99
100 self._elements = {}
101
102
103 box_main = wx.BoxSizer(wx.HORIZONTAL)
104 self.SetSizer(box_main)
105
106
107 self.add_artwork(box_main)
108
109
110 image_x, image_y = self.image.GetSize()
111
112
113 self._main_size = parent._size_x - image_x - self.art_spacing - 2*parent._border
114 if self.divider:
115 self._div_left = self.divider
116 self._div_right = self._main_size - self.divider
117 else:
118 self._div_left = self._div_right = self._main_size / 2
119
120
121 main_sizer = self._build_main_section(box_main)
122
123
124 self._add_title(main_sizer)
125
126
127 self.add_desc(main_sizer, max_y=self.height_desc)
128
129
130 main_sizer.AddStretchSpacer()
131 self.add_contents(main_sizer)
132
133
134 - def _add_title(self, sizer):
135 """Add the title to the dialog.
136
137 @param sizer: A sizer object.
138 @type sizer: wx.Sizer instance
139 """
140
141
142 sizer.AddSpacer(10)
143
144
145 title = wx.StaticText(self, -1, self.title)
146
147
148 title.SetFont(font.title)
149
150
151 sizer.Add(title, 0, wx.ALIGN_CENTRE|wx.ALL, 0)
152
153
154 sizer.AddSpacer(10)
155
156
157 - def _apply(self, event):
158 """Apply the operation.
159
160 @param event: The wx event.
161 @type event: wx event
162 """
163
164
165 self.exec_status = protected_exec(self.on_execute)
166
167
168 if not self.exec_status:
169 return
170
171
172 self.on_completion()
173
174
175 self.on_apply()
176
177
178 - def _build_main_section(self, sizer):
179 """Add the main part of the dialog.
180
181 @param sizer: A sizer object.
182 @type sizer: wx.Sizer instance
183 @return: The sizer object for the main part of the dialog.
184 @rtype: wx.Sizer instance
185 """
186
187
188 main_sizer = wx.BoxSizer(wx.VERTICAL)
189
190
191 sizer.Add(main_sizer, 1, wx.EXPAND|wx.ALL, 0)
192
193
194 return main_sizer
195
196
213
214
240
241
262
263
264 - def Clear(self, key):
265 """Special wizard method for clearing the value of the GUI element corresponding to the key.
266
267 @param key: The key corresponding to the desired GUI element.
268 @type key: str
269 """
270
271
272 self._elements[key].Clear()
273
274
275 - def GetValue(self, key):
276 """Special wizard method for getting the value of the GUI element corresponding to the key.
277
278 @param key: The key corresponding to the desired GUI element.
279 @type key: str
280 @return: The value that the specific GUI element's GetValue() method returns.
281 @rtype: unknown
282 """
283
284
285 return self._elements[key].GetValue()
286
287
288 - def ResetChoices(self, key, combo_choices=None, combo_data=None, combo_default=None):
289 """Special wizard method for resetting the list of choices in a ComboBox type element.
290
291 @param key: The key corresponding to the desired GUI element.
292 @type key: str
293 @keyword combo_choices: The list of choices to present to the user. This is only used if the element_type is set to 'combo'.
294 @type combo_choices: list of str
295 @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.
296 @type combo_data: list
297 @keyword combo_default: The default value of the ComboBox. This is only used if the element_type is set to 'combo'.
298 @type combo_default: str or None
299 """
300
301
302 self._elements[key].ResetChoices(combo_choices=combo_choices, combo_data=combo_data, combo_default=combo_default)
303
304
305 - def SetValue(self, key, value):
306 """Special wizard method for setting the value of the GUI element corresponding to the key.
307
308 @param key: The key corresponding to the desired GUI element.
309 @type key: str
310 @param value: The value that the specific GUI element's SetValue() method expects.
311 @type value: unknown
312 """
313
314
315 self._elements[key].SetValue(value)
316
317
318 - def add_artwork(self, sizer):
319 """Add the artwork to the dialog.
320
321 @param sizer: A sizer object.
322 @type sizer: wx.Sizer instance
323 """
324
325
326 if self.image_path:
327 self.image = wx.StaticBitmap(self, -1, wx.Bitmap(self.image_path, wx.BITMAP_TYPE_ANY))
328 sizer.Add(self.image, 0, wx.TOP|wx.ALIGN_CENTER_HORIZONTAL, 0)
329
330
331 sizer.AddSpacer(self.art_spacing)
332
333
334 - def add_contents(self, sizer):
335 """Add the specific GUI elements (dummy method).
336
337 @param sizer: A sizer object.
338 @type sizer: wx.Sizer instance
339 """
340
341
342 raise RelaxImplementError
343
344
345 - def add_desc(self, sizer, max_y=220):
346 """Add the description to the dialog.
347
348 @param sizer: A sizer object.
349 @type sizer: wx.Sizer instance
350 @keyword max_y: The maximum height, in number of pixels, for the description.
351 @type max_y: int
352 """
353
354
355 sizer.AddSpacer(5)
356 sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 0)
357 sizer.AddSpacer(5)
358
359
360 panel = scrolledpanel.ScrolledPanel(self, -1, name="desc")
361
362
363 panel_sizer = wx.BoxSizer(wx.VERTICAL)
364
365
366 text = wx.StaticText(panel, -1, self.main_text, style=wx.TE_MULTILINE)
367 text.SetFont(font.normal)
368
369
370 text.Wrap(self._main_size - 20)
371
372
373 x, y = text.GetSizeTuple()
374
375
376 if y > max_y-10:
377
378 panel.SetInitialSize((self._main_size, max_y))
379
380
381 else:
382
383 text.Wrap(self._main_size)
384
385
386 panel.SetInitialSize(text.GetSize())
387
388
389 panel_sizer.Add(text, 0, wx.ALIGN_LEFT, 0)
390
391
392 panel.SetSizer(panel_sizer)
393 panel.SetAutoLayout(1)
394 panel.SetupScrolling(scroll_x=False, scroll_y=True)
395 sizer.Add(panel, 0, wx.ALL|wx.EXPAND)
396
397
398 sizer.AddSpacer(5)
399 sizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.ALL, 0)
400 sizer.AddSpacer(5)
401
402
403 - def boolean_selector(self, sizer, desc, tooltip=None, divider=None, padding=0, spacer=None, default=True):
404 """Build the boolean selector widget for selecting between True and False.
405
406 @param sizer: The sizer to put the combo box widget into.
407 @type sizer: wx.Sizer instance
408 @param desc: The text description.
409 @type desc: str
410 @keyword tooltip: The tooltip which appears on hovering over the text or input field.
411 @type tooltip: str
412 @keyword divider: The optional position of the divider. If None, the class variable _div_left will be used.
413 @type divider: None or int
414 @keyword padding: Spacing to the left and right of the widgets.
415 @type padding: int
416 @keyword spacer: The amount of spacing to add below the field in pixels. If None, a stretchable spacer will be used.
417 @type spacer: None or int
418 @keyword default: The default boolean value.
419 @type default: bool
420 """
421
422
423 sub_sizer = wx.BoxSizer(wx.HORIZONTAL)
424
425
426 sub_sizer.AddSpacer(padding)
427
428
429 text = wx.StaticText(self, -1, desc, style=wx.ALIGN_LEFT)
430 text.SetFont(font.normal)
431 sub_sizer.Add(text, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
432
433
434 if not divider:
435 divider = self._div_left
436
437
438 x, y = text.GetSize()
439 sub_sizer.AddSpacer((divider - x, 0))
440
441
442 style = wx.CB_DROPDOWN | wx.CB_READONLY
443 combo = wx.ComboBox(self, -1, value=bool_to_gui(default), style=style, choices=['True', 'False'])
444 combo.SetMinSize((50, self.height_element))
445 combo.SetFont(font.normal)
446 sub_sizer.Add(combo, 1, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
447
448
449 sub_sizer.AddSpacer(padding)
450
451
452 sizer.Add(sub_sizer, 1, wx.EXPAND|wx.ALL, 0)
453
454
455 if spacer == None:
456 sizer.AddStretchSpacer()
457 else:
458 sizer.AddSpacer(spacer)
459
460
461 if tooltip:
462 text.SetToolTipString(tooltip)
463 combo.SetToolTipString(tooltip)
464
465
466 return combo
467
468
469 - def chooser(self, sizer, desc, func, choices):
470 """Build the choice element.
471
472 @param sizer: The sizer to put the input field into.
473 @type sizer: wx.Sizer instance
474 @param desc: The text description.
475 @type desc: str
476 @param func: The function to bind the event to
477 @type func: func
478 @param choices: The list of choices.
479 @type choices: list of str
480 """
481
482
483 sub_sizer = wx.BoxSizer(wx.HORIZONTAL)
484
485
486 text = wx.StaticText(self, -1, desc, style=wx.ALIGN_LEFT)
487 text.SetFont(font.normal)
488 sub_sizer.Add(text, 1, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
489
490
491 sub_sizer.AddSpacer(10)
492
493
494 type_choice = wx.Choice(self, -1, style=wx.ALIGN_LEFT, choices=choices)
495 sub_sizer.Add(type_choice, 1, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
496 type_choice.SetFont(font.normal)
497 self.Bind(wx.EVT_CHOICE, func, type_choice)
498
499
500 sizer.Add(sub_sizer)
501 sizer.AddStretchSpacer()
502
503
504 - def combo_box(self, sizer, desc, choices=[], evt_fn=None, tooltip=None, divider=None, padding=0, spacer=None, read_only=True):
505 """Build the combo box widget for list selections.
506
507 @param sizer: The sizer to put the combo box widget into.
508 @type sizer: wx.Sizer instance
509 @param desc: The text description.
510 @type desc: str
511 @param choices: The list of choices.
512 @type choices: list of str
513 @param evt_fn: The event handling function.
514 @type evt_fn: func
515 @keyword tooltip: The tooltip which appears on hovering over the text or input field.
516 @type tooltip: str
517 @keyword divider: The optional position of the divider. If None, the class variable _div_left will be used.
518 @type divider: None or int
519 @keyword padding: Spacing to the left and right of the widgets.
520 @type padding: int
521 @keyword spacer: The amount of spacing to add below the field in pixels. If None, a stretchable spacer will be used.
522 @type spacer: None or int
523 @keyword read_only: A flag which if True means that text cannot be typed into the combo box widget.
524 @type read_only: bool
525 @return: The combo box object.
526 @rtype: wx.ComboBox instance
527 """
528
529
530 sub_sizer = wx.BoxSizer(wx.HORIZONTAL)
531
532
533 sub_sizer.AddSpacer(padding)
534
535
536 text = wx.StaticText(self, -1, desc, style=wx.ALIGN_LEFT)
537 text.SetFont(font.normal)
538 sub_sizer.Add(text, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
539
540
541 if not divider:
542 divider = self._div_left
543
544
545 x, y = text.GetSize()
546 sub_sizer.AddSpacer((divider - x, 0))
547
548
549 style = wx.CB_DROPDOWN
550 if read_only:
551 style = style | wx.CB_READONLY
552 combo = wx.ComboBox(self, -1, value='', style=style, choices=choices)
553 combo.SetMinSize((50, self.height_element))
554 combo.SetFont(font.normal)
555 sub_sizer.Add(combo, 1, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
556
557
558 sub_sizer.AddSpacer(padding)
559
560
561 sizer.Add(sub_sizer, 1, wx.EXPAND|wx.ALL, 0)
562
563
564 if spacer == None:
565 sizer.AddStretchSpacer()
566 else:
567 sizer.AddSpacer(spacer)
568
569
570 if evt_fn:
571 self.Bind(wx.EVT_COMBOBOX, evt_fn, combo)
572
573
574 if tooltip:
575 text.SetToolTipString(tooltip)
576 combo.SetToolTipString(tooltip)
577
578
579 return combo
580
581
582 - def element_int(self, key=None, sizer=None, desc=None, tooltip=None, divider=None, padding=0, spacer=None):
583 """Set up the integer element and store it.
584
585 @keyword key: The dictionary key to store the element with.
586 @type key: str
587 @keyword sizer: The sizer to put the input field widget into.
588 @type sizer: wx.Sizer instance
589 @keyword desc: The text description.
590 @type desc: str
591 @keyword tooltip: The tooltip which appears on hovering over the text or input field.
592 @type tooltip: str
593 @keyword divider: The optional position of the divider. If None, the class variable _div_left will be used.
594 @type divider: None or int
595 @keyword padding: Spacing to the left and right of the widgets.
596 @type padding: int
597 @keyword spacer: The amount of spacing to add below the field in pixels. If None, a stretchable spacer will be used.
598 @type spacer: None or int
599 """
600
601
602 element = Integer(name=key, parent=self, sizer=sizer, desc=desc, tooltip=tooltip, divider=divider, padding=padding, spacer=spacer)
603
604
605 self._elements[key] = element
606
607
608 - def element_string(self, key=None, element_type='text', sizer=None, desc=None, combo_choices=None, combo_data=None, combo_default=None, tooltip=None, divider=None, padding=0, spacer=None, read_only=False):
609 """Set up the string element and store it.
610
611 @keyword key: The dictionary key to store the element with.
612 @type key: str
613 @keyword element_type: The type of GUI element to create. If set to 'text', a wx.TextCtrl element will be used. If set to 'combo', a wx.ComboBox element will be used.
614 @type element_type: str
615 @keyword sizer: The sizer to put the input field widget into.
616 @type sizer: wx.Sizer instance
617 @keyword desc: The text description.
618 @type desc: str
619 @keyword combo_choices: The list of choices to present to the user. This is only used if the element_type is set to 'combo'.
620 @type combo_choices: list of str
621 @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.
622 @type combo_data: list
623 @keyword combo_default: The default value of the ComboBox. This is only used if the element_type is set to 'combo'.
624 @type combo_default: str or None
625 @keyword tooltip: The tooltip which appears on hovering over the text or input field.
626 @type tooltip: str
627 @keyword divider: The optional position of the divider. If None, the class variable _div_left will be used.
628 @type divider: None or int
629 @keyword padding: Spacing to the left and right of the widgets.
630 @type padding: int
631 @keyword spacer: The amount of spacing to add below the field in pixels. If None, a stretchable spacer will be used.
632 @type spacer: None or int
633 @keyword read_only: A flag which if True means that the text of the element cannot be edited.
634 @type read_only: bool
635 """
636
637
638 element = String(name=key, parent=self, element_type=element_type, sizer=sizer, desc=desc, combo_choices=combo_choices, combo_data=combo_data, combo_default=combo_default, tooltip=tooltip, divider=divider, padding=padding, spacer=spacer, read_only=read_only)
639
640
641 self._elements[key] = element
642
643
644 - def element_string_list(self, key=None, element_type='default', sizer=None, desc=None, combo_choices=None, combo_data=None, combo_default=None, combo_list_size=None, tooltip=None, divider=None, padding=0, spacer=None):
645 """Set up the element and store it.
646
647 @keyword key: The dictionary key to store the element with.
648 @type key: str
649 @keyword element_type: The type of GUI element to create. If set to 'default', the wx.TextCtrl element with a button to bring up a dialog with ListCtrl will be used. If set to 'combo_list', the special gui.components.combo_list.Combo_list element will be used.
650 @type element_type: str
651 @keyword sizer: The sizer to put the input field widget into.
652 @type sizer: wx.Sizer instance
653 @keyword desc: The text description.
654 @type desc: str
655 @keyword combo_choices: The list of choices to present to the user. This is only used if the element_type is set to 'combo'.
656 @type combo_choices: list of str
657 @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.
658 @type combo_data: list
659 @keyword combo_default: The default value of the ComboBox. This is only used if the element_type is set to 'combo'.
660 @type combo_default: str or None
661 @keyword combo_list_size: The number of initial entries in a Combo_list object.
662 @type combo_list_size: int or None
663 @keyword tooltip: The tooltip which appears on hovering over the text or input field.
664 @type tooltip: str
665 @keyword divider: The optional position of the divider. If None, the class variable _div_left will be used.
666 @type divider: None or int
667 @keyword padding: Spacing to the left and right of the widgets.
668 @type padding: int
669 @keyword spacer: The amount of spacing to add below the field in pixels. If None, a stretchable spacer will be used.
670 @type spacer: None or int
671 """
672
673
674 element = String_list(name=key, element_type=element_type, parent=self, sizer=sizer, desc=desc, combo_choices=combo_choices, combo_data=combo_data, combo_default=combo_default, combo_list_size=combo_list_size, tooltip=tooltip, divider=divider, padding=padding, spacer=spacer)
675
676
677 self._elements[key] = element
678
679
680 - def element_string_list_of_lists(self, key=None, titles=None, sizer=None, desc=None, tooltip=None, divider=None, padding=0, spacer=None):
681 """Set up the element and store it.
682
683 @keyword key: The dictionary key to store the element with.
684 @type key: str
685 @keyword titles: The titles of each of the elements of the fixed width second dimension.
686 @type titles: list of str
687 @keyword sizer: The sizer to put the input field widget into.
688 @type sizer: wx.Sizer instance
689 @keyword desc: The text description.
690 @type desc: str
691 @keyword tooltip: The tooltip which appears on hovering over the text or input field.
692 @type tooltip: str
693 @keyword divider: The optional position of the divider. If None, the class variable _div_left will be used.
694 @type divider: None or int
695 @keyword padding: Spacing to the left and right of the widgets.
696 @type padding: int
697 @keyword spacer: The amount of spacing to add below the field in pixels. If None, a stretchable spacer will be used.
698 @type spacer: None or int
699 """
700
701
702 element = String_list_of_lists(name=key, titles=titles, parent=self, sizer=sizer, desc=desc, tooltip=tooltip, divider=divider, padding=padding, spacer=spacer)
703
704
705 self._elements[key] = element
706
707
708 - def file_selection(self, sizer, desc, message='File selection', wildcard=wx.FileSelectorDefaultWildcardStr, style=wx.FD_DEFAULT_STYLE, tooltip=None, divider=None, padding=0, spacer=None, preview=True):
709 """Build the file selection element.
710
711 @param sizer: The sizer to put the input field into.
712 @type sizer: wx.Sizer instance
713 @param desc: The text description.
714 @type desc: str
715 @keyword message: The file selector prompt string.
716 @type message: String
717 @keyword wildcard: The file wildcard pattern. For example for opening PDB files, this could be "PDB files (*.pdb)|*.pdb;*.PDB".
718 @type wildcard: String
719 @keyword style: The dialog style. To open a single file, set to wx.FD_OPEN. To open multiple files, set to wx.FD_OPEN|wx.FD_MULTIPLE. To save a single file, set to wx.FD_SAVE. To save multiple files, set to wx.FD_SAVE|wx.FD_MULTIPLE.
720 @type style: long
721 @keyword tooltip: The tooltip which appears on hovering over all the GUI elements.
722 @type tooltip: str
723 @keyword divider: The optional position of the divider. If None, the class variable _div_left will be used.
724 @type divider: None or int
725 @keyword padding: Spacing to the left and right of the widgets.
726 @type padding: int
727 @keyword spacer: The amount of spacing to add below the field in pixels. If None, a stretchable spacer will be used.
728 @type spacer: None or int
729 @keyword preview: A flag which if true will allow the file to be previewed.
730 @type preview: bool
731 @return: The file selection GUI element.
732 @rtype: wx.TextCtrl
733 """
734
735
736 sub_sizer = wx.BoxSizer(wx.HORIZONTAL)
737
738
739 sub_sizer.AddSpacer(padding)
740
741
742 text = wx.StaticText(self, -1, desc, style=wx.ALIGN_LEFT)
743 text.SetFont(font.normal)
744 sub_sizer.Add(text, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
745
746
747 if not divider:
748 divider = self._div_left
749
750
751 x, y = text.GetSize()
752 sub_sizer.AddSpacer((divider - x, 0))
753
754
755 if not hasattr(self, 'file_selection_field'):
756 self.file_selection_field = []
757 self.file_selection_field.append(wx.TextCtrl(self, -1, ''))
758 field = self.file_selection_field[-1]
759 field.SetMinSize((-1, self.height_element))
760 field.SetFont(font.normal)
761 sub_sizer.Add(field, 1, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
762
763
764 obj = RelaxFileDialog(self, field=field, message=message, wildcard=wildcard, style=style)
765
766
767 sub_sizer.AddSpacer(5)
768
769
770 button = wx.BitmapButton(self, -1, wx.Bitmap(paths.icon_16x16.open, wx.BITMAP_TYPE_ANY))
771 button.SetMinSize((self.height_element, self.height_element))
772 sub_sizer.Add(button, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
773 self.Bind(wx.EVT_BUTTON, obj.select_event, button)
774
775
776 if not hasattr(self, 'file_selection_preview_button'):
777 self.file_selection_preview_button = []
778 if not preview:
779 self.file_selection_preview_button.append(None)
780 else:
781
782 sub_sizer.AddSpacer(5)
783
784
785 self.file_selection_preview_button.append(wx.BitmapButton(self, -1, wx.Bitmap(paths.icon_16x16.document_preview, wx.BITMAP_TYPE_ANY)))
786 button = self.file_selection_preview_button[-1]
787 button.SetMinSize((self.height_element, self.height_element))
788 sub_sizer.Add(button, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
789 self.Bind(wx.EVT_BUTTON, self.preview_file, button)
790
791
792 sub_sizer.AddSpacer(padding)
793
794
795 sizer.Add(sub_sizer, 1, wx.EXPAND|wx.ALL, 0)
796
797
798 if spacer == None:
799 sizer.AddStretchSpacer()
800 else:
801 sizer.AddSpacer(spacer)
802
803
804 if tooltip:
805 text.SetToolTipString(tooltip)
806 field.SetToolTipString(tooltip)
807 button.SetToolTipString(tooltip)
808 else:
809 button.SetToolTipString("Select the file.")
810
811
812 return field
813
814
815 - def free_file_format(self, sizer, padding=10, spacer=3, data_cols=False, save=True, reset=True):
816 """Build the free format file settings widget.
817
818 @param sizer: The sizer to put the input field into.
819 @type sizer: wx.Sizer instance
820 @keyword padding: The size of the padding between the wx.StaticBoxSizer border and the internal elements, in pixels.
821 @type padding: int
822 @keyword spacer: The horizontal spacing between the elements, in pixels.
823 @type spacer: int
824 @keyword data_cols: A flag which if True causes the data and error column elements to be displayed.
825 @type data_cols: bool
826 @keyword save: A flag which if True will cause the save button to be displayed.
827 @type save: bool
828 @keyword reset: A flag which if True will cause the reset button to be displayed.
829 @type reset: bool
830 """
831
832
833 box = wx.StaticBox(self, -1, "Free format file settings")
834 box.SetFont(font.subtitle)
835
836
837 main_sizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
838 field_sizer = wx.BoxSizer(wx.VERTICAL)
839 button_sizer = wx.BoxSizer(wx.VERTICAL)
840
841
842 border = wx.BoxSizer()
843
844
845 border.Add(main_sizer, 1, wx.ALL|wx.EXPAND, 0)
846
847
848 sizer.Add(border, 0, wx.EXPAND)
849 sizer.AddStretchSpacer()
850
851
852 divider = self._div_left - border.GetMinSize()[0] / 2 - padding
853
854
855 self.spin_id_col = self.input_field(field_sizer, "Spin ID column:", divider=divider, padding=padding, spacer=spacer)
856 self.mol_name_col = self.input_field(field_sizer, "Molecule name column:", divider=divider, padding=padding, spacer=spacer)
857 self.res_num_col = self.input_field(field_sizer, "Residue number column:", divider=divider, padding=padding, spacer=spacer)
858 self.res_name_col = self.input_field(field_sizer, "Residue name column:", divider=divider, padding=padding, spacer=spacer)
859 self.spin_num_col = self.input_field(field_sizer, "Spin number column:", divider=divider, padding=padding, spacer=spacer)
860 self.spin_name_col = self.input_field(field_sizer, "Spin name column:", divider=divider, padding=padding, spacer=spacer)
861 if data_cols:
862 self.data_col = self.input_field(field_sizer, "Data column:", divider=divider, padding=padding, spacer=spacer)
863 self.err_col = self.input_field(field_sizer, "Error column:", divider=divider, padding=padding, spacer=spacer)
864
865
866 self.sep = self.combo_box(field_sizer, "Column separator:", ["white space", ",", ";", ":", ""], divider=divider, padding=padding, spacer=spacer, read_only=False)
867
868
869 main_sizer.Add(field_sizer, 1, wx.ALL|wx.EXPAND, 0)
870
871
872 self._free_file_format_set_vals()
873
874
875 if save or reset:
876
877 if save:
878
879 button = buttons.ThemedGenBitmapTextButton(self, -1, None, "")
880 button.SetBitmapLabel(wx.Bitmap(paths.icon_22x22.save, wx.BITMAP_TYPE_ANY))
881 button.SetFont(font.normal)
882 button.SetToolTipString("Save the free file format settings within the relax data store.")
883 button.SetMinSize(self.size_square_button)
884
885
886 button_sizer.Add(button, 0, wx.ADJUST_MINSIZE, 0)
887
888
889 button_sizer.AddSpacer(padding)
890
891
892 self.Bind(wx.EVT_BUTTON, self._free_file_format_save, button)
893
894
895 if reset:
896
897 button = buttons.ThemedGenBitmapTextButton(self, -1, None, "")
898 button.SetBitmapLabel(wx.Bitmap(paths.icon_22x22.edit_delete, wx.BITMAP_TYPE_ANY))
899 button.SetFont(font.normal)
900 button.SetToolTipString("Reset the free file format settings to the original values.")
901 button.SetMinSize(self.size_square_button)
902
903
904 button_sizer.Add(button, 0, wx.ADJUST_MINSIZE, 0)
905
906
907 self.Bind(wx.EVT_BUTTON, self._free_file_format_reset, button)
908
909
910 main_sizer.AddSpacer(padding)
911 main_sizer.Add(button_sizer, 0, wx.ALL, 0)
912
913
914 - def input_field(self, sizer, desc, tooltip=None, divider=None, padding=0, spacer=None):
915 """Build the input field widget.
916
917 @param sizer: The sizer to put the input field widget into.
918 @type sizer: wx.Sizer instance
919 @param desc: The text description.
920 @type desc: str
921 @keyword tooltip: The tooltip which appears on hovering over the text or input field.
922 @type tooltip: str
923 @keyword divider: The optional position of the divider. If None, the class variable _div_left will be used.
924 @type divider: None or int
925 @keyword padding: Spacing to the left and right of the widgets.
926 @type padding: int
927 @keyword spacer: The amount of spacing to add below the field in pixels. If None, a stretchable spacer will be used.
928 @type spacer: None or int
929 @return: The input field object.
930 @rtype: wx.TextCtrl instance
931 """
932
933
934 sub_sizer = wx.BoxSizer(wx.HORIZONTAL)
935
936
937 sub_sizer.AddSpacer(padding)
938
939
940 text = wx.StaticText(self, -1, desc, style=wx.ALIGN_LEFT)
941 text.SetFont(font.normal)
942 sub_sizer.Add(text, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
943
944
945 if not divider:
946 divider = self._div_left
947
948
949 x, y = text.GetSize()
950 sub_sizer.AddSpacer((divider - x, 0))
951
952
953 field = wx.TextCtrl(self, -1, '')
954 field.SetMinSize((50, self.height_element))
955 field.SetFont(font.normal)
956 sub_sizer.Add(field, 1, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
957
958
959 sub_sizer.AddSpacer(padding)
960
961
962 sizer.Add(sub_sizer, 1, wx.EXPAND|wx.ALL, 0)
963
964
965 if spacer == None:
966 sizer.AddStretchSpacer()
967 else:
968 sizer.AddSpacer(spacer)
969
970
971 if tooltip:
972 text.SetToolTipString(tooltip)
973 field.SetToolTipString(tooltip)
974
975
976 return field
977
978
979 - def on_apply(self):
980 """To be over-ridden if an action is to be performed on hitting the apply button.
981
982 This method will be called when clicking on the apply button.
983 """
984
985
986 - def on_completion(self):
987 """To be over-ridden if an action is to be performed just after executing self.on_execute().
988
989 This method is called just after self.on_execute() has been called
990 """
991
992
993 - def on_display(self):
994 """To be over-ridden if an action is to be performed prior to displaying the page.
995
996 This method will be called by the wizard class method _display_page() just after hiding all other pages but prior to displaying this page.
997 """
998
999
1000 - def on_display_post(self):
1001 """To be over-ridden if an action is to be performed after the execution of the on_display() method.
1002
1003 This method will be called by the wizard class method _display_page() just after hiding all other pages but prior to displaying this page.
1004 """
1005
1006
1007 - def on_execute(self):
1008 """To be over-ridden if an action is to be performed just before exiting the page.
1009
1010 This method is called when terminating the wizard or hitting the apply button.
1011 """
1012
1013
1014 - def on_init(self):
1015 """To be over-ridden if an action is to be performed when a page is newly displayed.
1016
1017 This method will be called by the wizard class method _display_page() at the very end.
1018 """
1019
1020
1021 - def on_next(self):
1022 """To be over-ridden if an action is to be performed just before moving to the next page.
1023
1024 This method is called when moving to the next page of the wizard.
1025 """
1026
1027
1028 - def preview_file(self, event):
1029 """Preview a file.
1030
1031 @param event: The wx event.
1032 @type event: wx event
1033 """
1034
1035
1036 button = event.GetEventObject()
1037 index = None
1038 for i in range(len(self.file_selection_preview_button)):
1039 if button == self.file_selection_preview_button[i]:
1040 index = i
1041 break
1042
1043
1044 if index == None:
1045 return
1046
1047
1048 file = gui_to_str(self.file_selection_field[index].GetValue())
1049
1050
1051 if file == None:
1052 return
1053
1054
1055 open_file(file, force_text=True)
1056
1057
1058 - def spin_control(self, sizer, desc, default='', min=0, max=100, tooltip=None, divider=None, padding=0, spacer=None):
1059 """Build the spin control widget.
1060
1061 @param sizer: The sizer to put the spin control widget into.
1062 @type sizer: wx.Sizer instance
1063 @param desc: The text description.
1064 @type desc: str
1065 @keyword default: The default value of the control.
1066 @type default: int
1067 @keyword min: The minimum value allowed.
1068 @type min: int
1069 @keyword max: The maximum value allowed.
1070 @type max: int
1071 @keyword tooltip: The tooltip which appears on hovering over the text or spin control.
1072 @type tooltip: str
1073 @keyword divider: The optional position of the divider. If None, the class variable _div_left will be used.
1074 @type divider: None or int
1075 @keyword padding: Spacing to the left and right of the widgets.
1076 @type padding: int
1077 @keyword spacer: The amount of spacing to add below the field in pixels. If None, a stretchable spacer will be used.
1078 @type spacer: None or int
1079 @return: The spin control object.
1080 @rtype: wx.TextCtrl instance
1081 """
1082
1083
1084 sub_sizer = wx.BoxSizer(wx.HORIZONTAL)
1085
1086
1087 sub_sizer.AddSpacer(padding)
1088
1089
1090 text = wx.StaticText(self, -1, desc, style=wx.ALIGN_LEFT)
1091 text.SetFont(font.normal)
1092 sub_sizer.Add(text, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
1093
1094
1095 if not divider:
1096 divider = self._div_left
1097
1098
1099 x, y = text.GetSize()
1100 sub_sizer.AddSpacer((divider - x, 0))
1101
1102
1103 field = wx.SpinCtrl(self, id=-1, initial=default, min=min, max=max)
1104 field.SetMinSize((50, self.height_element))
1105 field.SetFont(font.normal)
1106 sub_sizer.Add(field, 1, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
1107
1108
1109 sub_sizer.AddSpacer(padding)
1110
1111
1112 sizer.Add(sub_sizer, 1, wx.EXPAND|wx.ALL, 0)
1113
1114
1115 if spacer == None:
1116 sizer.AddStretchSpacer()
1117 else:
1118 sizer.AddSpacer(spacer)
1119
1120
1121 if tooltip:
1122 text.SetToolTipString(tooltip)
1123 field.SetToolTipString(tooltip)
1124
1125
1126 return field
1127
1128
1129 - def spin_id_element(self, sizer, desc="The spin ID string:", choices=['@N', '@C'], default=None, divider=None, padding=0, spacer=None):
1130 """Build a special the input field widget.
1131
1132 @param sizer: The sizer to put the input field widget into.
1133 @type sizer: wx.Sizer instance
1134 @keyword desc: The text description.
1135 @type desc: str
1136 @keyword choices: The list of choices to present to the user.
1137 @type choices: list of str
1138 @keyword default: The default value.
1139 @type default: str or None
1140 @keyword divider: The optional position of the divider. If None, the class variable _div_left will be used.
1141 @type divider: None or int
1142 @keyword padding: Spacing to the left and right of the widgets.
1143 @type padding: int
1144 @keyword spacer: The amount of spacing to add below the field in pixels. If None, a stretchable spacer will be used.
1145 @type spacer: None or int
1146 @return: The input field object.
1147 @rtype: wx.TextCtrl instance
1148 """
1149
1150
1151 sub_sizer = wx.BoxSizer(wx.HORIZONTAL)
1152
1153
1154 sub_sizer.AddSpacer(padding)
1155
1156
1157 text = wx.StaticText(self, -1, desc, style=wx.ALIGN_LEFT)
1158 text.SetFont(font.normal)
1159 sub_sizer.Add(text, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
1160
1161
1162 if not divider:
1163 divider = self._div_left
1164
1165
1166 x, y = text.GetSize()
1167 sub_sizer.AddSpacer((divider - x, 0))
1168
1169
1170 field = wx.ComboBox(self, -1, '', choices=choices)
1171 field.SetMinSize((50, self.height_element))
1172 field.SetFont(font.normal)
1173 sub_sizer.Add(field, 1, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
1174
1175
1176 field.SetValue(str_to_gui(default))
1177
1178
1179 sub_sizer.AddSpacer(padding)
1180
1181
1182 sizer.Add(sub_sizer, 1, wx.EXPAND|wx.ALL, 0)
1183
1184
1185 if spacer == None:
1186 sizer.AddStretchSpacer()
1187 else:
1188 sizer.AddSpacer(spacer)
1189
1190
1191 text.SetToolTipString(id_string_doc[1][1:-1])
1192 field.SetToolTipString(id_string_doc[1][1:-1])
1193
1194
1195 return field
1196
1197
1198 - def text(self, sizer, desc, default='', divider=None, padding=0, spacer=None):
1199 """Build the input field.
1200
1201 @param sizer: The sizer to put the input field into.
1202 @type sizer: wx.Sizer instance
1203 @param desc: The text description.
1204 @type desc: str
1205 @keyword default: The default text.
1206 @type default: str
1207 @keyword divider: The optional position of the divider. If None, the class variable _div_left will be used.
1208 @type divider: None or int
1209 @keyword padding: Spacing to the left and right of the widgets.
1210 @type padding: int
1211 @keyword spacer: The amount of spacing to add below the field in pixels. If None, a stretchable spacer will be used.
1212 @type spacer: None or int
1213 @return: The input field object.
1214 @rtype: wx.TextCtrl instance
1215 """
1216
1217
1218 sub_sizer = wx.BoxSizer(wx.HORIZONTAL)
1219
1220
1221 sub_sizer.AddSpacer(padding)
1222
1223
1224 text = wx.StaticText(self, -1, desc, style=wx.ALIGN_LEFT)
1225 text.SetFont(font.normal)
1226 sub_sizer.Add(text, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
1227
1228
1229 if not divider:
1230 divider = self._div_left
1231
1232
1233 x, y = text.GetSize()
1234 sub_sizer.AddSpacer((divider - x, 0))
1235
1236
1237 text = wx.TextCtrl(self, -1, default, style=wx.ALIGN_LEFT)
1238 text.SetEditable(False)
1239 text.SetFont(font.normal)
1240 colour = self.GetBackgroundColour()
1241 text.SetOwnBackgroundColour(colour)
1242 text.SetMinSize((self._div_right, self.height_element))
1243 sub_sizer.Add(text, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
1244
1245
1246 sub_sizer.AddSpacer(padding)
1247
1248
1249 sizer.Add(sub_sizer)
1250
1251
1252 if spacer == None:
1253 sizer.AddStretchSpacer()
1254 else:
1255 sizer.AddSpacer(spacer)
1256
1257
1258 return text
1259
1260
1261
1263 """The wizard."""
1264
1265
1266 _size_button = (100, 33)
1267 ICON_APPLY = paths.icon_22x22.dialog_ok_apply
1268 ICON_BACK = paths.icon_22x22.go_previous_view
1269 ICON_CANCEL = paths.icon_22x22.dialog_cancel
1270 ICON_FINISH = paths.icon_22x22.dialog_ok
1271 ICON_NEXT = paths.icon_22x22.go_next_view
1272 ICON_OK = paths.icon_22x22.dialog_ok
1273 ICON_SKIP = paths.icon_22x22.skip
1274 TEXT_APPLY = " Apply"
1275 TEXT_BACK = " Back"
1276 TEXT_CANCEL = " Cancel"
1277 TEXT_FINISH = " Finish"
1278 TEXT_NEXT = " Next"
1279 TEXT_OK = " OK"
1280 TEXT_SKIP = " Skip"
1281
1282
1283 - def __init__(self, parent=None, size_x=400, size_y=400, title='', border=10, style=wx.DEFAULT_DIALOG_STYLE):
1284 """Set up the window.
1285
1286 @keyword parent: The parent window.
1287 @type parent: wx.Window instance
1288 @keyword size_x: The width of the wizard.
1289 @type size_x: int
1290 @keyword size_y: The height of the wizard.
1291 @type size_y: int
1292 @keyword title: The title of the wizard dialog.
1293 @type title: str
1294 @keyword border: The size of the border inside the wizard.
1295 @type border: int
1296 @keyword style: The dialog style.
1297 @type style: wx style
1298 """
1299
1300
1301 self._size_x = size_x
1302 self._size_y = size_y
1303 self._border = border
1304
1305
1306 wx.Dialog.__init__(self, parent, id=-1, title=title, style=style)
1307
1308
1309 self.SetIcons(relax_icons)
1310
1311
1312 sizer = wx.BoxSizer(wx.VERTICAL)
1313 self.SetSizer(sizer)
1314
1315
1316 self._main_sizer = add_border(sizer, border=border, packing=wx.VERTICAL)
1317
1318
1319 self.SetSize((size_x, size_y))
1320
1321
1322 self.Centre()
1323
1324
1325 self._current_page = 0
1326 self._num_pages = 0
1327 self._pages = []
1328 self._page_sizers = []
1329 self._button_sizers = []
1330 self._button_apply_flag = []
1331 self._button_skip_flag = []
1332 self._buttons = []
1333 self._button_ids = []
1334 self._exec_on_next = []
1335 self._exec_count = []
1336 self._proceed_on_error = []
1337 self._uf_flush = []
1338 self._seq_fn_list = []
1339 self._seq_next = []
1340 self._seq_prev = []
1341 self._skip_flag = []
1342
1343
1344 for i in range(10):
1345
1346 self._pages.append(None)
1347
1348
1349 self._page_sizers.append(wx.BoxSizer(wx.VERTICAL))
1350
1351
1352 self._button_sizers.append(wx.BoxSizer(wx.HORIZONTAL))
1353
1354
1355 self._button_apply_flag.append(True)
1356 self._button_skip_flag.append(False)
1357
1358
1359 self._buttons.append({'back': None,
1360 'apply': None,
1361 'next': None,
1362 'ok': None,
1363 'finish': None,
1364 'cancel': None})
1365
1366
1367 self._button_ids.append({'back': wx.NewId(),
1368 'apply': wx.NewId(),
1369 'next': wx.NewId(),
1370 'ok': wx.NewId(),
1371 'finish': wx.NewId(),
1372 'cancel': wx.NewId()})
1373
1374
1375 self._exec_on_next.append(True)
1376
1377
1378 self._exec_count.append(0)
1379
1380
1381 self._proceed_on_error.append(True)
1382
1383
1384 self._uf_flush.append(False)
1385
1386
1387 self._seq_fn_list.append(self._next_fn)
1388 self._seq_next.append(None)
1389 self._seq_prev.append(None)
1390
1391
1392 self._skip_flag.append(False)
1393
1394
1491
1492
1494 """Cancel the operation.
1495
1496 @param event: The wx event.
1497 @type event: wx event
1498 """
1499
1500
1501 self.Close()
1502
1503
1504 - def _display_page(self, i):
1505 """Display the given page.
1506
1507 @param i: The index of the page to display.
1508 @type i: int
1509 """
1510
1511
1512 for j in range(self._num_pages):
1513 if self._main_sizer.IsShown(self._page_sizers[j]):
1514 self._main_sizer.Hide(self._page_sizers[j])
1515
1516
1517 if status.show_gui:
1518 self._main_sizer.Show(self._page_sizers[i])
1519
1520
1521 self._pages[i].on_display()
1522 self._pages[i].on_display_post()
1523
1524
1525 self.Layout()
1526 self.Refresh()
1527
1528
1529 self._pages[i].on_init()
1530
1531
1533 """Return to the previous page.
1534
1535 @param event: The wx event.
1536 @type event: wx event
1537 """
1538
1539
1540 self._current_page = self._seq_prev[self._current_page]
1541
1542
1543 self._display_page(self._current_page)
1544
1545
1547 """Move to the next page.
1548
1549 @param event: The wx event.
1550 @type event: wx event
1551 """
1552
1553
1554 if not self._skip_flag[self._current_page]:
1555
1556 self._pages[self._current_page].on_next()
1557
1558
1559 if self._exec_on_next[self._current_page]:
1560 self._pages[self._current_page]._apply(event)
1561
1562
1563 if self._uf_flush[self._current_page]:
1564 interpreter.flush()
1565
1566
1567 if not self._pages[self._current_page].exec_status:
1568
1569 if not self._proceed_on_error[self._current_page]:
1570 return
1571
1572
1573 self._exec_count[self._current_page] += 1
1574
1575
1576 next_page = self._seq_fn_list[self._current_page]()
1577
1578
1579 if self._pages[next_page] == None:
1580 self._ok(None)
1581 return
1582
1583
1584 self._seq_next[self._current_page] = next_page
1585 self._seq_prev[next_page] = self._current_page
1586
1587
1588 self._current_page = next_page
1589
1590
1591 self._display_page(self._current_page)
1592
1593
1595 """Standard function for setting the next page to the one directly next in the sequence.
1596
1597 @return: The index of the next page, which is the current page index plus one.
1598 @rtype: int
1599 """
1600
1601
1602 return self._current_page + 1
1603
1604
1605 - def _ok(self, event):
1606 """Accept the operation.
1607
1608 @param event: The wx event.
1609 @type event: wx event
1610 """
1611
1612
1613 for i in self._seq_loop():
1614 if not self._exec_count[i] and not self._skip_flag[i]:
1615
1616 self._pages[i]._apply(event)
1617
1618
1619 if self._uf_flush[i]:
1620 interpreter.flush()
1621
1622
1623 if not self._pages[self._current_page].exec_status:
1624
1625 if not self._proceed_on_error[self._current_page]:
1626 return
1627
1628
1629 self._exec_count[i] += 1
1630
1631
1632 if self.IsModal():
1633 self.EndModal(wx.ID_OK)
1634 else:
1635 self.Close()
1636
1637
1639 """Loop over the sequence in the forwards direction."""
1640
1641
1642 current = 0
1643
1644
1645 yield current
1646
1647
1648 while True:
1649
1650 next = self._seq_next[current]
1651 current = next
1652
1653
1654 if next == None:
1655 break
1656
1657
1658 yield next
1659
1660
1661 - def _skip(self, event):
1662 """Skip the page.
1663
1664 @param event: The wx event.
1665 @type event: wx event
1666 """
1667
1668
1669 self._skip_flag[self._current_page] = True
1670
1671
1672 self._go_next(None)
1673
1674
1675 - def add_page(self, panel, apply_button=True, skip_button=False, exec_on_next=True, proceed_on_error=True, uf_flush=False):
1676 """Add a new page to the wizard.
1677
1678 @param panel: The page to add to the wizard.
1679 @type panel: wx.Panel instance
1680 @keyword apply_button: A flag which if true will show the apply button for that page.
1681 @type apply_button: bool
1682 @keyword skip_button: A flag which if true will show the skip button for that page.
1683 @type skip_button: bool
1684 @keyword exec_on_next: A flag which if true will run the on_execute() method when clicking on the next button.
1685 @type exec_on_next: bool
1686 @keyword proceed_on_error: A flag which if True will proceed to the next page (or quit if there are no more pages) despite the occurrence of an error in execution. If False, the page will remain open (the GUI interpreter thread will be flushed first to synchronise).
1687 @type proceed_on_error: bool
1688 @keyword uf_flush: A flag which if True will cause the GUI interpreter thread to be flushed to clear out all user function call prior to proceeding.
1689 @type uf_flush: bool
1690 @return: The index of the page in the wizard.
1691 @rtype: int
1692 """
1693
1694
1695 index = self._num_pages
1696 self._num_pages += 1
1697 self._pages[index] = panel
1698
1699
1700 self._main_sizer.Add(self._page_sizers[index], 1, wx.ALL|wx.EXPAND, 0)
1701
1702
1703 top_sizer = wx.BoxSizer(wx.VERTICAL)
1704 self._page_sizers[index].Add(top_sizer, 1, wx.ALL|wx.EXPAND, 0)
1705
1706
1707 top_sizer.Add(panel, 1, wx.ALL|wx.EXPAND, 0)
1708
1709
1710 self._page_sizers[index].Add(self._button_sizers[index], 0, wx.ALIGN_RIGHT|wx.ALL, 0)
1711
1712
1713 self._button_apply_flag[index] = apply_button
1714 self._button_skip_flag[index] = skip_button
1715 self._exec_on_next[index] = exec_on_next
1716 self._proceed_on_error[index] = proceed_on_error
1717 if not proceed_on_error or uf_flush:
1718 self._uf_flush[index] = True
1719
1720
1721 panel.page_index = self._num_pages - 1
1722
1723
1724 return panel.page_index
1725
1726
1728 """Prevent moving forwards (or unblock).
1729
1730 @keyword block: A flag which if True will block forwards movement and if False will unblock.
1731 @type block: bool
1732 """
1733
1734
1735 buttons = ['next', 'ok', 'finish']
1736
1737
1738 for i in range(len(buttons)):
1739
1740 button = self._buttons[self._current_page][buttons[i]]
1741 if button == None:
1742 continue
1743
1744
1745 if block:
1746 button.Disable()
1747
1748
1749 else:
1750 button.Enable()
1751
1752
1753 - def get_page(self, index):
1754 """Get a page from the wizard.
1755
1756 @param index: The index of the page.
1757 @type index: int
1758 @return: The page object.
1759 @rtype: Wiz_page instance.
1760 """
1761
1762
1763 return self._pages[index]
1764
1765
1766 - def run(self, modal=False):
1767 """Execute the wizard.
1768
1769 @keyword modal: A flag which if True will cause the wizard to be run as a modal dialog.
1770 @type modal: bool
1771 @return: The status from the modal operation, i.e. True if the wizard is run, False if cancelled or other error occur. For modeless operation, this returns nothing.
1772 @rtype: bool or None
1773 """
1774
1775
1776 for i in range(self._num_pages):
1777 if self._pages[i].setup_fail:
1778 return
1779
1780
1781 self._build_buttons()
1782
1783
1784 self._display_page(0)
1785
1786
1787 if not status.show_gui:
1788 return
1789
1790
1791 if modal:
1792
1793 wiz_status = self.ShowModal()
1794
1795
1796 return wiz_status
1797
1798
1799 else:
1800
1801 self.Show()
1802
1803
1805 """A user specified function for non-linear page changing.
1806
1807 @param index: The index of the page the function should be associated with.
1808 @type index: int
1809 @param fn: The function for determining the page after the current. This function should return the index of the next page.
1810 @type fn: func or method.
1811 """
1812
1813
1814 self._seq_fn_list[index] = fn
1815