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 a set of special GUI elements to be used in the relax wizards."""
25
26
27 from string import upper
28 import sys
29 import wx
30 import wx.lib.mixins.listctrl
31
32
33 from relax_errors import RelaxError
34 from status import Status; status = Status()
35
36
37 from gui.components.combo_list import Combo_list
38 from gui.fonts import font
39 from gui.misc import add_border, gui_to_int, gui_to_list, gui_to_str, int_to_gui, list_to_gui, str_to_gui
40 from gui import paths
41
42
44 """Base wizard GUI element for the input of all types of lists."""
45
46 - def __init__(self, name=None, parent=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):
47 """Set up the base value element.
48
49
50 @keyword name: The name of the element to use in titles, etc.
51 @type name: str
52 @keyword parent: The wizard GUI element.
53 @type parent: wx.Panel instance
54 @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.
55 @type element_type: str
56 @param sizer: The sizer to put the input field widget into.
57 @type sizer: wx.Sizer instance
58 @param desc: The text description.
59 @type desc: str
60 @keyword combo_choices: The list of choices to present to the user. This is only used if the element_type is set to 'combo'.
61 @type combo_choices: list of str
62 @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.
63 @type combo_data: list
64 @keyword combo_default: The default value of the ComboBox. This is only used if the element_type is set to 'combo'.
65 @type combo_default: str or None
66 @keyword tooltip: The tooltip which appears on hovering over the text or input field.
67 @type tooltip: str
68 @keyword divider: The optional position of the divider. If None, the class variable _div_left will be used.
69 @type divider: None or int
70 @keyword padding: Spacing to the left and right of the widgets.
71 @type padding: int
72 @keyword spacer: The amount of spacing to add below the field in pixels. If None, a stretchable spacer will be used.
73 @type spacer: None or int
74 @keyword read_only: A flag which if True means that the text of the element cannot be edited.
75 @type read_only: bool
76 """
77
78
79 self.name = name
80 self.element_type = element_type
81
82
83 sub_sizer = wx.BoxSizer(wx.HORIZONTAL)
84
85
86 sub_sizer.AddSpacer(padding)
87
88
89 text = wx.StaticText(parent, -1, desc, style=wx.ALIGN_LEFT)
90 text.SetFont(font.normal)
91 sub_sizer.Add(text, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
92
93
94 if not divider:
95 divider = parent._div_left
96
97
98 x, y = text.GetSize()
99 sub_sizer.AddSpacer((divider - x, 0))
100
101
102 if element_type == 'text':
103
104 self._field = wx.TextCtrl(parent, -1, '')
105
106
107 if read_only:
108
109 self._field.SetEditable(False)
110
111
112 colour = parent.GetBackgroundColour()
113 self._field.SetOwnBackgroundColour(colour)
114
115
116 elif element_type == 'combo':
117
118 style = wx.CB_DROPDOWN
119 if read_only:
120 style = style | wx.CB_READONLY
121
122
123 self._field = wx.ComboBox(parent, -1, '', style=style)
124
125
126 self.ResetChoices(combo_choices=combo_choices, combo_data=combo_data, combo_default=combo_default)
127
128
129 else:
130 raise RelaxError("Unknown element type '%s'." % element_type)
131
132
133 self._field.SetMinSize((50, parent.height_element))
134 self._field.SetFont(font.normal)
135 sub_sizer.Add(self._field, 1, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
136
137
138 sub_sizer.AddSpacer(padding)
139
140
141 sizer.Add(sub_sizer, 1, wx.EXPAND|wx.ALL, 0)
142
143
144 if spacer == None:
145 sizer.AddStretchSpacer()
146 else:
147 sizer.AddSpacer(spacer)
148
149
150 if tooltip:
151 text.SetToolTipString(tooltip)
152 self._field.SetToolTipString(tooltip)
153
154
155 self.conversion_fns()
156
157
159 """Special method for clearing or resetting the GUI element."""
160
161
162 if self.element_type in ['text', 'combo']:
163 self._field.Clear()
164
165
167 """Special method for returning the value of the GUI element.
168
169 @return: The string list value.
170 @rtype: list of str
171 """
172
173
174 if self.element_type == 'text':
175 return self.convert_from_gui(self._field.GetValue())
176
177
178 if self.element_type == 'combo':
179 return self.convert_from_gui(self._field.GetClientData(self._field.GetSelection()))
180
181
182 - def ResetChoices(self, combo_choices=None, combo_data=None, combo_default=None):
183 """Special wizard method for resetting the list of choices in a ComboBox type element.
184
185 @param key: The key corresponding to the desired GUI element.
186 @type key: str
187 @keyword combo_choices: The list of choices to present to the user. This is only used if the element_type is set to 'combo'.
188 @type combo_choices: list of str
189 @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.
190 @type combo_data: list
191 @keyword combo_default: The default value of the ComboBox. This is only used if the element_type is set to 'combo'.
192 @type combo_default: str or None
193 """
194
195
196 if self.element_type == 'text':
197 raise RelaxError("Cannot reset the list of ComboBox choices as this is a TextCtrl!")
198
199
200 if self.element_type == 'combo':
201
202 self.Clear()
203
204
205 if combo_data == None:
206 combo_data = combo_choices
207
208
209 for i in range(len(combo_choices)):
210 self._field.Insert(str_to_gui(combo_choices[i]), i, combo_data[i])
211
212
213 if combo_default:
214 self._field.SetStringSelection(combo_default)
215
216
218 """Special method for setting the value of the GUI element.
219
220 @param value: The value to set.
221 @type value: list of str
222 """
223
224
225 if self.element_type == 'text':
226 self._field.SetValue(self.convert_to_gui(value))
227
228
229 if self.element_type == 'combo':
230
231 for i in range(self._field.GetCount()):
232 if self._field.GetClientData(i) == value:
233 self._field.SetSelection(i)
234 break
235
236
238 """Dummy method for setting up the conversion functions.
239
240 This should define the self.convert_to_gui() and self.convert_from_gui() function aliases.
241 """
242
243
244
246 """Wizard GUI element for the input of integers."""
247
249 """Set up the conversion functions."""
250
251 self.convert_from_gui = gui_to_int
252 self.convert_to_gui = int_to_gui
253
254
256 """Base wizard GUI element for the input of all types of lists."""
257
258 - def __init__(self, name=None, parent=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):
259 """Set up the element.
260
261 @keyword name: The name of the element to use in titles, etc.
262 @type name: str
263 @keyword parent: The wizard GUI element.
264 @type parent: wx.Panel instance
265 @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.
266 @type element_type: str
267 @keyword sizer: The sizer to put the input field widget into.
268 @type sizer: wx.Sizer instance
269 @keyword desc: The text description.
270 @type desc: str
271 @keyword combo_choices: The list of choices to present to the user. This is only used if the element_type is set to 'combo'.
272 @type combo_choices: list of str
273 @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.
274 @type combo_data: list
275 @keyword combo_default: The default value of the ComboBox. This is only used if the element_type is set to 'combo'.
276 @type combo_default: str or None
277 @keyword combo_list_size: The number of initial entries in a Combo_list object.
278 @type combo_list_size: int or None
279 @keyword tooltip: The tooltip which appears on hovering over the text or input field.
280 @type tooltip: str
281 @keyword divider: The optional position of the divider. If None, the class variable _div_left will be used.
282 @type divider: None or int
283 @keyword padding: Spacing to the left and right of the widgets.
284 @type padding: int
285 @keyword spacer: The amount of spacing to add below the field in pixels. If None, a stretchable spacer will be used.
286 @type spacer: None or int
287 """
288
289
290 self.name = name
291
292
293 if element_type == 'default':
294
295 sub_sizer = wx.BoxSizer(wx.HORIZONTAL)
296
297
298 sub_sizer.AddSpacer(padding)
299
300
301 text = wx.StaticText(parent, -1, desc, style=wx.ALIGN_LEFT)
302 text.SetFont(font.normal)
303 sub_sizer.Add(text, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0)
304
305
306 if not divider:
307 divider = parent._div_left
308
309
310 x, y = text.GetSize()
311 sub_sizer.AddSpacer((divider - x, 0))
312
313
314 self._field = wx.TextCtrl(parent, -1, '')
315 self._field.SetMinSize((50, parent.height_element))
316 self._field.SetFont(font.normal)
317 self._field.SetEditable(False)
318 colour = parent.GetBackgroundColour()
319 self._field.SetOwnBackgroundColour(colour)
320 sub_sizer.Add(self._field, 1, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
321
322
323 sub_sizer.AddSpacer(5)
324
325
326 button = wx.BitmapButton(parent, -1, wx.Bitmap(paths.icon_16x16.edit_rename, wx.BITMAP_TYPE_ANY))
327 button.SetMinSize((parent.height_element, parent.height_element))
328 sub_sizer.Add(button, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0)
329 parent.Bind(wx.EVT_BUTTON, self.open_dialog, button)
330
331
332 sub_sizer.AddSpacer(padding)
333
334
335 sizer.Add(sub_sizer, 1, wx.EXPAND|wx.ALL, 0)
336
337
338 if spacer == None:
339 sizer.AddStretchSpacer()
340 else:
341 sizer.AddSpacer(spacer)
342
343
344 if tooltip:
345 text.SetToolTipString(tooltip)
346 self._field.SetToolTipString(tooltip)
347
348
349 elif element_type == 'combo_list':
350 self._field = Combo_list(parent, sizer, desc, n=combo_list_size, choices=combo_choices, tooltip=tooltip)
351
352
353 else:
354 raise RelaxError("Unknown element type '%s'." % element_type)
355
356
358 """Special method for returning the value of the GUI element.
359
360 @return: The string list value.
361 @rtype: list of str
362 """
363
364
365 return gui_to_list(self._field.GetValue())
366
367
369 """Special method for setting the value of the GUI element.
370
371 @param value: The value to set.
372 @type value: list of str
373 """
374
375
376 self._field.SetValue(list_to_gui(value))
377
378
380 """Dummy method which must be overridden."""
381
382
384 """Open a special dialog for inputting a list of text values.
385
386 @param event: The wx event.
387 @type event: wx event
388 """
389
390
391 win = self.init_window()
392
393
394 win.SetValue(self.GetValue())
395
396
397 if status.show_gui:
398 win.ShowModal()
399 win.Close()
400
401
402 self.SetValue(win.GetValue())
403
404
405 del win
406
407
408
410 """Wizard GUI element for the input of strings."""
411
413 """Set up the conversion functions."""
414
415 self.convert_from_gui = gui_to_str
416 self.convert_to_gui = str_to_gui
417
418
419
421 """Wizard GUI element for the input of lists of strings."""
422
428
429
430
432 """Wizard GUI element for the input of a list of lists of strings."""
433
434 - def __init__(self, name=None, titles=None, parent=None, sizer=None, desc=None, tooltip=None, divider=None, padding=0, spacer=None):
435 """Set up the element.
436
437 @keyword name: The name of the element to use in titles, etc.
438 @type name: str
439 @keyword titles: The titles of each of the elements of the fixed width second dimension.
440 @type titles: list of str
441 @keyword parent: The wizard GUI element.
442 @type parent: wx.Panel instance
443 @keyword sizer: The sizer to put the input field widget into.
444 @type sizer: wx.Sizer instance
445 @keyword desc: The text description.
446 @type desc: str
447 @keyword tooltip: The tooltip which appears on hovering over the text or input field.
448 @type tooltip: str
449 @keyword divider: The optional position of the divider. If None, the class variable _div_left will be used.
450 @type divider: None or int
451 @keyword padding: Spacing to the left and right of the widgets.
452 @type padding: int
453 @keyword spacer: The amount of spacing to add below the field in pixels. If None, a stretchable spacer will be used.
454 @type spacer: None or int
455 """
456
457
458 self.titles = titles
459
460
461 List.__init__(self, name=name, parent=parent, sizer=sizer, desc=desc, tooltip=tooltip, divider=divider, padding=padding, spacer=spacer)
462
463
469
470
471
472 -class String_list_ctrl(wx.ListCtrl, wx.lib.mixins.listctrl.TextEditMixin, wx.lib.mixins.listctrl.ListCtrlAutoWidthMixin):
473 """The string list ListCtrl object."""
474
476 """Initialise the control.
477
478 @param parent: The parent window.
479 @type parent: wx.Frame instance
480 """
481
482
483 wx.ListCtrl.__init__(self, parent, -1, style=wx.BORDER_SUNKEN|wx.LC_REPORT|wx.LC_HRULES|wx.LC_VRULES)
484 wx.lib.mixins.listctrl.TextEditMixin.__init__(self)
485 wx.lib.mixins.listctrl.ListCtrlAutoWidthMixin.__init__(self)
486
487
488
490 """The string list editor window."""
491
492
493 SIZE = (600, 600)
494
495
496 BORDER = 10
497
498
499 SIZE_BUTTON = (150, 33)
500
502 """Set up the string list editor window.
503
504 @keyword name: The name of the window.
505 @type name: str
506 """
507
508
509 self.name = name
510
511
512 title = "The list of %s" % name
513
514
515 wx.Dialog.__init__(self, None, id=-1, title=title)
516
517
518 width = self.SIZE[0] - 2*self.BORDER
519
520
521 self.SetSize(self.SIZE)
522 self.Centre()
523 self.SetFont(font.normal)
524
525
526 main_sizer = wx.BoxSizer(wx.VERTICAL)
527
528
529 self.SetSizer(main_sizer)
530
531
532 sizer = add_border(main_sizer, border=self.BORDER, packing=wx.VERTICAL)
533
534
535 self.add_list(sizer)
536
537
538 sizer.AddSpacer(self.BORDER)
539
540
541 self.add_buttons(sizer)
542
543
545 """Return the values as a list of strings.
546
547 @return: The list of values.
548 @rtype: list of str
549 """
550
551
552 values = []
553
554
555 for i in range(self.list.GetItemCount()):
556 values.append(gui_to_str(self.list.GetItemText(i)))
557
558
559 return values
560
561
563 """Set up the list values.
564
565 @param values: The list of values to add to the list.
566 @type values: list of str
567 """
568
569
570 for i in range(len(values)):
571 self.list.InsertStringItem(i, str_to_gui(values[i]))
572
573
616
617
619 """Set up the list control.
620
621 @param sizer: A sizer object.
622 @type sizer: wx.Sizer instance
623 """
624
625
626 self.list = String_list_ctrl(self)
627
628
629 title = "%s%s" % (upper(self.name[0]), self.name[1:])
630
631
632 self.list.InsertColumn(0, title)
633 self.list.SetColumnWidth(0, wx.LIST_AUTOSIZE)
634
635
636 sizer.Add(self.list, 1, wx.ALL|wx.EXPAND, 0)
637
638
640 """Append a new row to the list.
641
642 @param event: The wx event.
643 @type event: wx event
644 """
645
646
647 next = self.list.GetItemCount()
648
649
650 self.list.InsertStringItem(next, '')
651
652
654 """Close the window.
655
656 @param event: The wx event.
657 @type event: wx event
658 """
659
660
661 self.Destroy()
662
663
665 """Remove all items from the list.
666
667 @param event: The wx event.
668 @type event: wx event
669 """
670
671
672 self.list.DeleteAllItems()
673
674
675
677 """The string list of lists editor window."""
678
679
680 SIZE = (600, 600)
681
682
683 BORDER = 10
684
685
686 SIZE_BUTTON = (150, 33)
687
688 - def __init__(self, name='', titles=None):
689 """Set up the string list editor window.
690
691 @keyword name: The name of the window.
692 @type name: str
693 @keyword titles: The titles of each of the elements of the fixed width second dimension.
694 @type titles: list of str
695 """
696
697
698 self.name = name
699 self.titles = titles
700
701
702 self.num = len(self.titles)
703
704
705 title = "The list of %s" % name
706
707
708 wx.Dialog.__init__(self, None, id=-1, title=title)
709
710
711 self.width = self.SIZE[0] - 2*self.BORDER
712
713
714 self.SetSize(self.SIZE)
715 self.Centre()
716 self.SetFont(font.normal)
717
718
719 main_sizer = wx.BoxSizer(wx.VERTICAL)
720
721
722 self.SetSizer(main_sizer)
723
724
725 sizer = add_border(main_sizer, border=self.BORDER, packing=wx.VERTICAL)
726
727
728 self.add_list(sizer)
729
730
731 sizer.AddSpacer(self.BORDER)
732
733
734 self.add_buttons(sizer)
735
736
738 """Return the values as a list of lists of strings.
739
740 @return: The list of lists of values.
741 @rtype: list of lists of str
742 """
743
744
745 values = []
746
747
748 for i in range(self.list.GetItemCount()):
749
750 values.append([])
751
752
753 for j in range(self.num):
754
755 item = self.list.GetItem(i, j)
756
757
758 values[-1].append(gui_to_str(item.GetText()))
759
760
761 return values
762
763
765 """Set up the list of lists values.
766
767 @param values: The list of lists of values to add to the list.
768 @type values: list of lists of str
769 """
770
771
772 for i in range(len(values)):
773
774 self.list.InsertStringItem(sys.maxint, str_to_gui(values[i][0]))
775
776
777 for j in range(1, self.num):
778
779 self.list.SetStringItem(i, j, str_to_gui(values[i][j]))
780
781
782 self.Refresh()
783
784
827
828
830 """Set up the list control.
831
832 @param sizer: A sizer object.
833 @type sizer: wx.Sizer instance
834 """
835
836
837 self.list = String_list_ctrl(self)
838
839
840 title = "%s%s" % (upper(self.name[0]), self.name[1:])
841
842
843 for i in range(self.num):
844 self.list.InsertColumn(i, self.titles[i])
845 self.list.SetColumnWidth(i, self.width/self.num)
846
847
848 sizer.Add(self.list, 1, wx.ALL|wx.EXPAND, 0)
849
850
852 """Append a new row to the list.
853
854 @param event: The wx event.
855 @type event: wx event
856 """
857
858
859 next = self.list.GetItemCount()
860
861
862 self.list.InsertStringItem(next, '')
863
864
866 """Close the window.
867
868 @param event: The wx event.
869 @type event: wx event
870 """
871
872
873 self.Destroy()
874
875
877 """Remove all items from the list.
878
879 @param event: The wx event.
880 @type event: wx event
881 """
882
883
884 self.list.DeleteAllItems()
885