Package gui :: Package input_elements :: Module sequence
[hide private]
[frames] | no frames]

Source Code for Module gui.input_elements.sequence

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2012,2014 Edward d'Auvergne                                   # 
  4  #                                                                             # 
  5  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  6  #                                                                             # 
  7  # This program is free software: you can redistribute it and/or modify        # 
  8  # it under the terms of the GNU General Public License as published by        # 
  9  # the Free Software Foundation, either version 3 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # This program is distributed in the hope that it will be useful,             # 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 15  # GNU General Public License for more details.                                # 
 16  #                                                                             # 
 17  # You should have received a copy of the GNU General Public License           # 
 18  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 19  #                                                                             # 
 20  ############################################################################### 
 21   
 22  # Module docstring. 
 23  """Module containing a set of special GUI elements to be used in the relax wizards.""" 
 24   
 25  # Python module imports. 
 26  import wx 
 27  import wx.lib.mixins.listctrl 
 28   
 29  # relax module imports. 
 30  from graphics import fetch_icon 
 31  from gui.input_elements.combo_list import Combo_list 
 32  from gui.fonts import font 
 33  from gui.misc import add_border 
 34  from gui.string_conv import float_to_gui, gui_to_float, gui_to_int, gui_to_list, gui_to_py, gui_to_str, gui_to_tuple, int_to_gui, list_to_gui, py_to_gui, str_to_gui, tuple_to_gui 
 35  from lib.check_types import is_list 
 36  from lib.errors import RelaxError 
 37  from status import Status; status = Status() 
 38   
 39   
40 -class Sequence:
41 """Wizard GUI element for the input of all types of Python sequence objects. 42 43 The supported Python types include: 44 - list of floats 45 - list of integers 46 - list of strings 47 - tuple of floats 48 - tuple of integers 49 - tuple of strings 50 """ 51
52 - def __init__(self, name=None, default=None, parent=None, element_type='default', seq_type=None, value_type=None, dim=None, min=0, max=1000, sizer=None, titles=None, desc=None, combo_choices=None, combo_data=None, combo_list_min=None, tooltip=None, divider=None, padding=0, spacer=None, height_element=27, single_value=False, read_only=False, can_be_none=False):
53 """Set up the element. 54 55 @keyword name: The name of the element to use in titles, etc. 56 @type name: str 57 @keyword default: The default value of the element. 58 @type default: sequence object 59 @keyword parent: The wizard GUI element. 60 @type parent: wx.Panel instance 61 @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. 62 @type element_type: str 63 @keyword seq_type: The type of Python sequence. This should be one of 'list' or 'tuple'. 64 @type seq_type: str 65 @keyword value_type: The type of Python object that the value should be. This can be one of 'float', 'int', or 'str'. 66 @type value_type: str 67 @keyword dim: The dimensions that a list or tuple must conform to. For a 1D sequence, this can be a single value or a tuple of possible sizes. For a 2D sequence (a numpy matrix or list of lists), this must be a tuple of the fixed dimension sizes, e.g. a 3x5 matrix should be specified as (3, 5). 68 @type dim: int, tuple of int or None 69 @keyword min: For a SpinCtrl, the minimum value allowed. 70 @type min: int 71 @keyword max: For a SpinCtrl, the maximum value allowed. 72 @type max: int 73 @keyword sizer: The sizer to put the input field widget into. 74 @type sizer: wx.Sizer instance 75 @keyword titles: The titles of each of the elements of the fixed dimension elements. 76 @type titles: list of str 77 @keyword desc: The text description. 78 @type desc: str 79 @keyword combo_choices: The list of choices to present to the user. This is only used if the element_type is set to 'combo'. 80 @type combo_choices: list of str 81 @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. 82 @type combo_data: list 83 @keyword combo_list_min: The minimum length for the Combo_list object. 84 @type combo_list_min: int or None 85 @keyword tooltip: The tooltip which appears on hovering over the text or input field. 86 @type tooltip: str 87 @keyword divider: The position of the divider. 88 @type divider: int 89 @keyword padding: Spacing to the left and right of the widgets. 90 @type padding: int 91 @keyword spacer: The amount of spacing to add below the field in pixels. If None, a stretchable spacer will be used. 92 @type spacer: None or int 93 @keyword height_element: The height in pixels of the GUI element. 94 @type height_element: int 95 @keyword single_value: A flag which if True will cause single input values to be treated as single values rather than a list or tuple. 96 @type single_value: bool 97 @keyword read_only: A flag which if True means that the text of the element cannot be edited. 98 @type read_only: bool 99 @keyword can_be_none: A flag which specifies if the element is allowed to have the None value. 100 @type can_be_none: bool 101 """ 102 103 # Store the args. 104 self.parent = parent 105 self.name = name 106 self.default = default 107 self.element_type = element_type 108 self.seq_type = seq_type 109 self.value_type = value_type 110 self.dim = dim 111 self.min = min 112 self.max = max 113 self.titles = titles 114 self.single_value = single_value 115 self.can_be_none = can_be_none 116 117 # The base types. 118 if value_type in ['float', 'num']: 119 self.convert_from_gui = gui_to_float 120 self.convert_to_gui = float_to_gui 121 elif value_type == 'int': 122 self.convert_from_gui = gui_to_int 123 self.convert_to_gui = int_to_gui 124 elif value_type == 'str': 125 self.convert_from_gui = gui_to_str 126 self.convert_to_gui = str_to_gui 127 else: 128 self.convert_from_gui = gui_to_py 129 self.convert_to_gui = py_to_gui 130 131 # The sequence types. 132 if seq_type == 'list': 133 self.convert_from_gui_seq = gui_to_list 134 self.convert_to_gui_seq = list_to_gui 135 elif seq_type == 'tuple': 136 self.convert_from_gui_seq = gui_to_tuple 137 self.convert_to_gui_seq = tuple_to_gui 138 else: 139 raise RelaxError("Unknown sequence type '%s'." % seq_type) 140 141 # Initialise the default element. 142 if self.element_type == 'default': 143 # Translate the read_only flag if None. 144 if read_only == None: 145 read_only = False 146 147 # Init. 148 sub_sizer = wx.BoxSizer(wx.HORIZONTAL) 149 150 # Left padding. 151 sub_sizer.AddSpacer(padding) 152 153 # The description. 154 text = wx.StaticText(parent, -1, desc, style=wx.ALIGN_LEFT) 155 text.SetFont(font.normal) 156 sub_sizer.Add(text, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 0) 157 158 # The divider. 159 if not divider: 160 raise RelaxError("The divider position has not been supplied.") 161 162 # Spacing. 163 x, y = text.GetSize() 164 sub_sizer.AddSpacer((divider - x, 0)) 165 166 # The input field. 167 self._field = wx.TextCtrl(parent, -1, '') 168 self._field.SetMinSize((50, height_element)) 169 self._field.SetFont(font.normal) 170 sub_sizer.Add(self._field, 1, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0) 171 172 # Read-only. 173 if read_only: 174 self._field.SetEditable(False) 175 colour = parent.GetBackgroundColour() 176 self._field.SetOwnBackgroundColour(colour) 177 178 # A little spacing. 179 sub_sizer.AddSpacer(5) 180 181 # The edit button. 182 button = wx.BitmapButton(parent, -1, wx.Bitmap(fetch_icon('oxygen.actions.edit-rename', "16x16"), wx.BITMAP_TYPE_ANY)) 183 button.SetMinSize((height_element, height_element)) 184 button.SetToolTipString("Edit the values.") 185 sub_sizer.Add(button, 0, wx.ADJUST_MINSIZE|wx.ALIGN_CENTER_VERTICAL, 0) 186 parent.Bind(wx.EVT_BUTTON, self.open_dialog, button) 187 188 # Right padding. 189 sub_sizer.AddSpacer(padding) 190 191 # Add to the main sizer. 192 sizer.Add(sub_sizer, 1, wx.EXPAND|wx.ALL, 0) 193 194 # Spacing below the widget. 195 if spacer == None: 196 sizer.AddStretchSpacer() 197 else: 198 sizer.AddSpacer(spacer) 199 200 # Tooltip. 201 if tooltip: 202 text.SetToolTipString(tooltip) 203 self._field.SetToolTipString(tooltip) 204 205 # Set the default value. 206 if self.default is not None: 207 self._field.SetValue(self.convert_to_gui_seq(self.default)) 208 209 # Initialise the combo list input field. 210 elif self.element_type == 'combo_list': 211 # Translate the read_only flag if None. 212 if read_only == None: 213 read_only = False 214 215 # Correct the min_length argument. 216 if combo_list_min == None: 217 combo_list_min = 1 218 219 # Set up the Combo_list object. 220 self._field = Combo_list(parent, sizer, desc, value_type=value_type, min_length=combo_list_min, choices=combo_choices, data=combo_data, default=default, tooltip=tooltip, read_only=read_only, can_be_none=can_be_none) 221 222 # Unknown field. 223 else: 224 raise RelaxError("Unknown element type '%s'." % self.element_type)
225 226
227 - def Clear(self):
228 """Special method for clearing or resetting the GUI element.""" 229 230 # Clear the value from a TextCtrl or ComboBox. 231 if self.element_type in ['default', 'combo_list']: 232 self._field.Clear()
233 234
235 - def GetValue(self):
236 """Special method for returning the sequence values of the GUI element. 237 238 @return: The sequence of values. 239 @rtype: sequence type 240 """ 241 242 # The value. 243 value = self._field.GetValue() 244 245 # Handle Combo_list elements. 246 if self.element_type == 'combo_list': 247 # Empty lists. 248 if value == [] or value == None: 249 return None 250 251 # Non Combo_list elements. 252 else: 253 # Handle single values. 254 value_set = False 255 if self.single_value: 256 try: 257 # Convert. 258 value = self.convert_from_gui(value) 259 260 # Check that the conversion was successful. 261 if value == None and self.can_be_none: 262 value_set = True 263 elif self.value_type == None: 264 value_set = True 265 elif self.value_type in ['float', 'num']: 266 if isinstance(value, int) or isinstance(value, float): 267 value_set = True 268 elif self.value_type == 'int': 269 if isinstance(value, int): 270 value_set = True 271 elif self.value_type == 'str': 272 if self.seq_type == 'list' and value[0] != '[': 273 value_set = True 274 elif self.seq_type == 'tuple' and value[0] != '(': 275 value_set = True 276 except: 277 pass 278 279 # Convert to a sequence, handling bad user behaviour. 280 if not value_set: 281 try: 282 value = self.convert_from_gui_seq(value) 283 284 # Set the value to None or an empty sequence. 285 except RelaxError: 286 if self.can_be_none: 287 value = None 288 elif self.seq_type == 'list': 289 value = [] 290 else: 291 value = () 292 293 # Handle all other errors. 294 except: 295 value = None 296 297 # Nothing to do. 298 if value == None: 299 return None 300 301 # Convert sequences to single values as needed. 302 if self.single_value: 303 if (isinstance(value, list) or isinstance(value, tuple)) and len(value) == 1: 304 value = value[0] 305 306 # Convert single values to sequences as needed. 307 elif value != None: 308 if self.seq_type == 'list' and not isinstance(value, list): 309 value = [value] 310 elif self.seq_type == 'tuple' and not isinstance(value, tuple): 311 value = (value,) 312 313 # Handle empty list and tuple values. 314 if not self.single_value and len(value) == 0: 315 return None 316 317 # Return the value. 318 return value
319 320
321 - def SetValue(self, value=None, index=None):
322 """Special method for setting the value of the GUI element. 323 324 @keyword value: The value to set. 325 @type value: value or list of values 326 @keyword index: The index of the value to set, if the full list is not given. 327 @type index: int or None 328 """ 329 330 # The ComboBox list. 331 if self.element_type == 'combo_list': 332 self._field.SetValue(value=value, index=index) 333 334 # The other elements. 335 else: 336 # Handle single values. 337 if self.single_value and isinstance(value, list) and len(value) == 1: 338 value = value[0] 339 340 # Convert and set the value. 341 self._field.SetValue(self.convert_to_gui_seq(value))
342 343
344 - def UpdateChoices(self, combo_choices=None, combo_data=None, combo_default=None):
345 """Special wizard method for updating the list of choices in a ComboBox type element. 346 347 @keyword combo_choices: The list of choices to present to the user. This is only used if the element_type is set to 'combo_list'. 348 @type combo_choices: list of str 349 @keyword combo_data: The data returned by a call to GetValue(). This is only used if the element_type is set to 'combo_list'. 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. 350 @type combo_data: list 351 @keyword combo_default: The default value of the ComboBox. This is only used if the element_type is set to 'combo_list'. 352 @type combo_default: str or None 353 """ 354 355 # The ComboBox list. 356 if self.element_type == 'combo_list': 357 self._field.UpdateChoices(combo_choices=combo_choices, combo_data=combo_data, combo_default=combo_default)
358 359
360 - def open_dialog(self, event):
361 """Open a special dialog for inputting a list of text values. 362 363 @param event: The wx event. 364 @type event: wx event 365 """ 366 367 # Show the window. 368 self.selection_win_show() 369 370 # Extract the data from the selection window once closed. 371 self.selection_win_data() 372 373 # Destroy the window. 374 self.sel_win.Destroy() 375 del self.sel_win
376 377
378 - def selection_win_data(self):
379 """Extract the data from the selection window.""" 380 381 # Get the value. 382 value = self.sel_win.GetValue() 383 384 # No sequence data. 385 if value == None or not len(value): 386 self.Clear() 387 388 # Set the values. 389 else: 390 self.SetValue(value)
391 392
393 - def selection_win_show(self):
394 """Show the selection window.""" 395 396 # Destroy any pre-existing sequence window. 397 if hasattr(self, 'sel_win'): 398 self.sel_win.Destroy() 399 del self.sel_win 400 401 # Initialise the model selection window. 402 self.sel_win = Sequence_window(parent=self.parent, name=self.name, seq_type=self.seq_type, value_type=self.value_type, titles=self.titles, dim=self.dim) 403 404 # Set the model selector window selections. 405 self.sel_win.SetValue(self.GetValue()) 406 407 # Show the model selector window. 408 if status.show_gui: 409 self.sel_win.ShowModal() 410 self.sel_win.Close()
411 412 413
414 -class Sequence_list_ctrl(wx.ListCtrl, wx.lib.mixins.listctrl.TextEditMixin, wx.lib.mixins.listctrl.ListCtrlAutoWidthMixin):
415 """The string list ListCtrl object.""" 416
417 - def __init__(self, parent):
418 """Initialise the control. 419 420 @param parent: The parent window. 421 @type parent: wx.Frame instance 422 """ 423 424 # Execute the parent __init__() methods. 425 wx.ListCtrl.__init__(self, parent, -1, style=wx.BORDER_SUNKEN|wx.LC_REPORT|wx.LC_HRULES|wx.LC_VRULES) 426 wx.lib.mixins.listctrl.TextEditMixin.__init__(self) 427 wx.lib.mixins.listctrl.ListCtrlAutoWidthMixin.__init__(self) 428 429 # Catch edits. 430 self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.begin_label_edit)
431 432
433 - def begin_label_edit(self, event):
434 """Catch edits to make the first column read only. 435 436 @param event: The wx event. 437 @type event: wx event 438 """ 439 440 # Prevent edits in the first column. 441 if event.m_col == 0: 442 event.Veto() 443 444 # Otherwise the user is free to edit. 445 else: 446 event.Skip()
447 448 449
450 -class Sequence_window(wx.Dialog):
451 """The Python sequence object editor window.""" 452 453 # The window size. 454 SIZE = (800, 600) 455 456 # A border. 457 BORDER = 10 458 459 # Sizes. 460 SIZE_BUTTON = (150, 33) 461
462 - def __init__(self, parent=None, name='', seq_type='list', value_type='str', dim=None, titles=None):
463 """Set up the string list editor window. 464 465 @keyword parent: The parent GUI element. 466 @type parent: wx.Window instance or None 467 @keyword name: The name of the window. 468 @type name: str 469 @keyword seq_type: The type of Python sequence. This should be one of 'list' or 'tuple'. 470 @type seq_type: str 471 @keyword value_type: The type of Python data expected in the sequence. This should be one of 'float', 'int', or 'str'. 472 @type value_type: str 473 @keyword dim: The fixed dimension that the sequence must conform to. 474 @type dim: int or None 475 @keyword titles: The titles of each of the elements of the fixed dimension elements. 476 @type titles: list of str 477 """ 478 479 # Store the args. 480 self.name = name 481 self.seq_type = seq_type 482 self.value_type = value_type 483 self.dim = dim 484 self.titles = titles 485 486 # The base types. 487 if value_type in ['float', 'num']: 488 self.convert_from_gui = gui_to_float 489 self.convert_to_gui = float_to_gui 490 elif value_type == 'int': 491 self.convert_from_gui = gui_to_int 492 self.convert_to_gui = int_to_gui 493 elif value_type == 'str': 494 self.convert_from_gui = gui_to_str 495 self.convert_to_gui = str_to_gui 496 else: 497 raise RelaxError("Unknown base data type '%s'." % value_type) 498 499 # Variable length. 500 if not hasattr(self, 'variable_length'): 501 self.variable_length = False 502 self.offset = 0 503 if dim == None: 504 self.variable_length = True 505 self.offset = 1 506 507 # The title of the dialog. 508 title = "Edit the %s values." % name 509 510 # Set up the dialog. 511 wx.Dialog.__init__(self, parent, id=-1, title=title) 512 513 # Initialise some values 514 self.width = self.SIZE[0] - 2*self.BORDER 515 516 # Set the frame properties. 517 self.SetSize(self.SIZE) 518 self.Centre() 519 self.SetFont(font.normal) 520 521 # The main box sizer. 522 main_sizer = wx.BoxSizer(wx.VERTICAL) 523 524 # Pack the sizer into the frame. 525 self.SetSizer(main_sizer) 526 527 # Build the central sizer, with borders. 528 sizer = add_border(main_sizer, border=self.BORDER, packing=wx.VERTICAL) 529 530 # Add the list control. 531 self.add_list(sizer) 532 533 # Some spacing. 534 sizer.AddSpacer(self.BORDER) 535 536 # Add the bottom buttons. 537 self.add_buttons(sizer) 538 539 # Initialise the list of elements to a single element. 540 if not self.sequence.GetItemCount(): 541 self.add_element()
542 543
544 - def GetValue(self):
545 """Return the values as a sequence of values. 546 547 @return: The sequence of values. 548 @rtype: sequence type 549 """ 550 551 # Init. 552 values = [] 553 554 # Loop over the entries. 555 for i in range(self.sequence.GetItemCount()): 556 # Get the text. 557 item = self.sequence.GetItem(i, col=1) 558 text = item.GetText() 559 560 # Store the text. 561 try: 562 value = self.convert_from_gui(text) 563 except: 564 value = None 565 values.append(value) 566 567 # Sequence conversion. 568 if self.seq_type == 'tuple': 569 values = tuple(values) 570 571 # Check that something is set. 572 empty = True 573 for i in range(len(values)): 574 if values[i] != None: 575 empty = False 576 break 577 578 # Return nothing. 579 if empty: 580 return None 581 582 # Return the sequence. 583 return values
584 585
586 - def SetValue(self, values):
587 """Set up the list values. 588 589 @param values: The list of values to add to the list. 590 @type values: list of str or None 591 """ 592 593 # No value. 594 if values == None: 595 return 596 597 # Invalid list, so do nothing. 598 if not self.variable_length and is_list(values) and len(values) != self.dim: 599 return 600 601 # Single values. 602 try: 603 len(values) 604 except TypeError: 605 if self.seq_type == 'list': 606 values = [values] 607 elif self.seq_type == 'tuple': 608 values = (values,) 609 610 # Loop over the entries. 611 for i in range(len(values)): 612 # Fixed dimension sequences - set the values of the pre-created list. 613 if not self.variable_length: 614 self.sequence.SetStringItem(i, 1, self.convert_to_gui(values[i])) 615 616 # Variable dimension sequences - append the item to the end of the blank list. 617 else: 618 # The first element already exists. 619 if i != 0: 620 # First add the index+1. 621 self.sequence.InsertStringItem(i, int_to_gui(i+1)) 622 623 # Then set the value. 624 self.sequence.SetStringItem(i, 1, self.convert_to_gui(values[i]))
625 626
627 - def add_buttons(self, sizer):
628 """Add the buttons to the sizer. 629 630 @param sizer: A sizer object. 631 @type sizer: wx.Sizer instance 632 """ 633 634 # Create a horizontal layout for the buttons. 635 button_sizer = wx.BoxSizer(wx.HORIZONTAL) 636 sizer.Add(button_sizer, 0, wx.ALIGN_CENTER|wx.ALL, 0) 637 638 # The non-fixed sequence buttons. 639 if self.variable_length: 640 # The add button. 641 button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " Add") 642 button.SetBitmapLabel(wx.Bitmap(fetch_icon('oxygen.actions.list-add-relax-blue', "22x22"), wx.BITMAP_TYPE_ANY)) 643 button.SetFont(font.normal) 644 button.SetToolTipString("Add an item to the list.") 645 button.SetMinSize(self.SIZE_BUTTON) 646 button_sizer.Add(button, 0, wx.ADJUST_MINSIZE, 0) 647 self.Bind(wx.EVT_BUTTON, self.add_element, button) 648 649 # Spacer. 650 button_sizer.AddSpacer(20) 651 652 # The delete button. 653 button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " Delete") 654 button.SetBitmapLabel(wx.Bitmap(fetch_icon('oxygen.actions.list-remove', "22x22"), wx.BITMAP_TYPE_ANY)) 655 button.SetFont(font.normal) 656 button.SetToolTipString("Delete the last item.") 657 button.SetMinSize(self.SIZE_BUTTON) 658 button_sizer.Add(button, 0, wx.ADJUST_MINSIZE, 0) 659 self.Bind(wx.EVT_BUTTON, self.delete, button) 660 661 # Spacer. 662 button_sizer.AddSpacer(20) 663 664 # The delete all button. 665 button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " Delete all") 666 button.SetBitmapLabel(wx.Bitmap(fetch_icon('oxygen.actions.edit-delete', "22x22"), wx.BITMAP_TYPE_ANY)) 667 button.SetFont(font.normal) 668 button.SetToolTipString("Delete all items.") 669 button.SetMinSize(self.SIZE_BUTTON) 670 button_sizer.Add(button, 0, wx.ADJUST_MINSIZE, 0) 671 self.Bind(wx.EVT_BUTTON, self.delete_all, button) 672 673 # Spacer. 674 button_sizer.AddSpacer(20) 675 676 # The Ok button. 677 button = wx.lib.buttons.ThemedGenBitmapTextButton(self, -1, None, " Ok") 678 button.SetBitmapLabel(wx.Bitmap(fetch_icon('oxygen.actions.dialog-ok', "22x22"), wx.BITMAP_TYPE_ANY)) 679 button.SetFont(font.normal) 680 button.SetMinSize(self.SIZE_BUTTON) 681 button_sizer.Add(button, 0, wx.ADJUST_MINSIZE, 0) 682 self.Bind(wx.EVT_BUTTON, self.close, button)
683 684
685 - def add_element(self, event=None):
686 """Append a new row to the list. 687 688 @keyword event: The wx event. 689 @type event: wx event 690 """ 691 692 # The next index. 693 next = self.sequence.GetItemCount() 694 695 # Add a new row with the index at the start. 696 if self.variable_length: 697 self.sequence.InsertStringItem(next, int_to_gui(next+1)) 698 699 # Add a new empty row. 700 else: 701 self.sequence.InsertStringItem(next, str_to_gui(''))
702 703
704 - def add_list(self, sizer):
705 """Set up the list control. 706 707 @param sizer: A sizer object. 708 @type sizer: wx.Sizer instance 709 """ 710 711 # The control. 712 self.sequence = Sequence_list_ctrl(self) 713 714 # Set the column title. 715 title = "%s%s" % (self.name[0].upper(), self.name[1:]) 716 717 # Add the index column. 718 if self.titles: 719 self.sequence.InsertColumn(0, "Title") 720 self.sequence.SetColumnWidth(0, 200) 721 else: 722 self.sequence.InsertColumn(0, "Number") 723 self.sequence.SetColumnWidth(0, 70) 724 725 # Add a single column, full width. 726 self.sequence.InsertColumn(1, title) 727 self.sequence.SetColumnWidth(1, wx.LIST_AUTOSIZE) 728 729 # Add the table to the sizer. 730 sizer.Add(self.sequence, 1, wx.ALL|wx.EXPAND, 0) 731 732 # The fixed dimension sequence - add all the rows needed. 733 if not self.variable_length: 734 for i in range(self.dim): 735 # Add a new row. 736 self.add_element() 737 738 # Add a title to the first column. 739 if self.titles: 740 self.sequence.SetStringItem(i, 0, str_to_gui(self.titles[i])) 741 742 # Otherwise add numbers starting from 1. 743 else: 744 self.sequence.SetStringItem(i, 0, int_to_gui(i+1))
745 746
747 - def close(self, event):
748 """Close the window. 749 750 @param event: The wx event. 751 @type event: wx event 752 """ 753 754 # Close the window. 755 self.Close()
756 757
758 - def delete(self, event):
759 """Remove the last item from the list. 760 761 @param event: The wx event. 762 @type event: wx event 763 """ 764 765 # Delete the last item. 766 item = self.sequence.GetItemCount() 767 self.sequence.DeleteItem(item-1) 768 769 # If the list is empty, start again with a single blank element. 770 if not self.sequence.GetItemCount(): 771 self.add_element()
772 773
774 - def delete_all(self, event):
775 """Remove all items from the list. 776 777 @param event: The wx event. 778 @type event: wx event 779 """ 780 781 # Delete. 782 self.sequence.DeleteAllItems() 783 784 # Start again with a single blank element. 785 self.add_element()
786