Package gui :: Package spin_viewer :: Module tree
[hide private]
[frames] | no frames]

Source Code for Module gui.spin_viewer.tree

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2010-2012 Edward d'Auvergne                                   # 
  4  #                                                                             # 
  5  # This file is part of the program relax.                                     # 
  6  #                                                                             # 
  7  # relax 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 2 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # relax 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 relax; if not, write to the Free Software                        # 
 19  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   # 
 20  #                                                                             # 
 21  ############################################################################### 
 22   
 23  # Module docstring. 
 24  """The molecule, residue, and spin tree view GUI elements.""" 
 25   
 26   
 27  # Python module imports. 
 28  import wx 
 29   
 30  # relax module imports. 
 31  from generic_fns.selection import is_mol_selected, is_res_selected, is_spin_selected 
 32  from generic_fns.mol_res_spin import get_molecule_ids, get_residue_ids, get_spin_ids, molecule_loop, residue_loop, spin_loop 
 33  from generic_fns.pipes import get_pipe 
 34  from status import Status; status = Status() 
 35   
 36  # relax GUI module imports. 
 37  from gui import paths 
 38  from gui.components.menu import build_menu_item 
 39  from gui.message import Question 
 40  from gui.misc import gui_to_str 
 41  from gui.user_functions import User_functions 
 42   
 43   
44 -class Mol_res_spin_tree(wx.Window):
45 """The tree view class.""" 46 47 # Some IDs for the menu entries. 48 MENU_ROOT_MOLECULE_CREATE = wx.NewId() 49 MENU_ROOT_LOAD_SPINS = wx.NewId() 50 MENU_SPIN_SPIN_DELETE = wx.NewId() 51 MENU_SPIN_SPIN_SELECT = wx.NewId() 52 MENU_SPIN_SPIN_DESELECT = wx.NewId() 53 MENU_RESIDUE_SPIN_ADD = wx.NewId() 54 MENU_RESIDUE_RESIDUE_DELETE = wx.NewId() 55 MENU_RESIDUE_RESIDUE_SELECT = wx.NewId() 56 MENU_RESIDUE_RESIDUE_DESELECT = wx.NewId() 57 MENU_MOLECULE_RESIDUE_CREATE = wx.NewId() 58 MENU_MOLECULE_MOLECULE_DELETE = wx.NewId() 59 MENU_MOLECULE_MOLECULE_DESELECT = wx.NewId() 60 MENU_MOLECULE_MOLECULE_SELECT = wx.NewId() 61
62 - def __init__(self, gui, parent=None, id=None):
63 """Set up the tree GUI element. 64 65 @param gui: The gui object. 66 @type gui: wx object 67 @keyword parent: The parent GUI element that this is to be attached to. 68 @type parent: wx object 69 @keyword id: The ID number. 70 @type id: int 71 """ 72 73 # Store the args. 74 self.gui = gui 75 self.parent = parent 76 77 # Execute the base class method. 78 wx.Window.__init__(self, parent, id, style=wx.WANTS_CHARS) 79 80 # Some default values. 81 self.icon_size = 22 82 83 # The tree. 84 self.tree = wx.TreeCtrl(parent=self, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.TR_DEFAULT_STYLE) 85 86 # A tracking structure for the tree IDs. 87 self.tree_ids = {} 88 89 # Resize the tree element. 90 self.Bind(wx.EVT_SIZE, self._resize) 91 92 # The tree roots. 93 self.root = self.tree.AddRoot("Spin system information") 94 self.tree.SetPyData(self.root, "root") 95 96 # Build the icon list. 97 icon_list = wx.ImageList(self.icon_size, self.icon_size) 98 99 # The normal icons. 100 self.icon_mol_index = icon_list.Add(wx.Bitmap(paths.icon_22x22.molecule, wx.BITMAP_TYPE_ANY)) 101 self.icon_mol_unfold_index = icon_list.Add(wx.Bitmap(paths.icon_22x22.molecule_unfolded, wx.BITMAP_TYPE_ANY)) 102 self.icon_res_index = icon_list.Add(wx.Bitmap(paths.icon_22x22.residue, wx.BITMAP_TYPE_ANY)) 103 self.icon_spin_index = icon_list.Add(wx.Bitmap(paths.icon_22x22.spin, wx.BITMAP_TYPE_ANY)) 104 105 # The deselected icons. 106 self.icon_mol_index_desel = icon_list.Add(wx.Bitmap(paths.icon_22x22.molecule_grey, wx.BITMAP_TYPE_ANY)) 107 self.icon_mol_unfold_index_desel = icon_list.Add(wx.Bitmap(paths.icon_22x22.molecule_unfolded_grey, wx.BITMAP_TYPE_ANY)) 108 self.icon_res_index_desel = icon_list.Add(wx.Bitmap(paths.icon_22x22.residue_grey, wx.BITMAP_TYPE_ANY)) 109 self.icon_spin_index_desel = icon_list.Add(wx.Bitmap(paths.icon_22x22.spin_grey, wx.BITMAP_TYPE_ANY)) 110 111 # Set the icon list. 112 self.tree.SetImageList(icon_list) 113 114 # Some weird black magic (this is essential)!! 115 self.icon_list = icon_list 116 117 # Populate the tree. 118 self.update() 119 120 # Catch mouse events. 121 self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self._selection) 122 self.tree.Bind(wx.EVT_RIGHT_DOWN, self._right_click)
123 124
125 - def _resize(self, event):
126 """Resize the tree element. 127 128 @param event: The wx event. 129 @type event: wx event 130 """ 131 132 # The panel dimensions. 133 width, height = self.GetClientSizeTuple() 134 135 # Set the tree dimensions. 136 self.tree.SetDimensions(0, 0, width, height)
137 138
139 - def _right_click(self, event):
140 """Handle right clicks in the tree. 141 142 @param event: The wx event. 143 @type event: wx event 144 """ 145 146 # Obtain the position. 147 pos = event.GetPosition() 148 149 # Find the item clicked on. 150 item, flags = self.tree.HitTest(pos) 151 152 # The python data (with catch for wxPython 2.9 behaviour). 153 if not item.IsOk(): 154 self.info = None 155 else: 156 self.info = self.tree.GetItemPyData(item) 157 158 # Bring up the default menu. 159 if self.info == None: 160 self.menu_default() 161 162 # Bring up the root menu. 163 elif self.info == 'root': 164 self.menu_root() 165 166 # Bring up the molecule menu. 167 elif self.info['type'] == 'mol': 168 self.menu_molecule() 169 170 # Bring up the residue menu. 171 elif self.info['type'] == 'res': 172 self.menu_residue() 173 174 # Bring up the spin menu. 175 elif self.info['type'] == 'spin': 176 self.menu_spin()
177 178
179 - def _selection(self, event):
180 """Handle changes in selection in the tree. 181 182 @param event: The wx event. 183 @type event: wx event 184 """ 185 186 # Find the item clicked on. 187 item = event.GetItem() 188 189 # The python data. 190 info = self.tree.GetItemPyData(item) 191 192 # Display the container. 193 self.gui.spin_viewer.container.display(info)
194 195
196 - def create_molecule(self, event):
197 """Wrapper method. 198 199 @param event: The wx event. 200 @type event: wx event 201 """ 202 203 # Set up the user functions. 204 user_functions = User_functions(self.gui.spin_viewer) 205 206 # Call the dialog. 207 user_functions.molecule.create()
208 209
210 - def create_residue(self, event):
211 """Wrapper method. 212 213 @param event: The wx event. 214 @type event: wx event 215 """ 216 217 # Set up the user functions. 218 user_functions = User_functions(self.gui.spin_viewer) 219 220 # Call the dialog. 221 user_functions.residue.create(mol_name=self.info['mol_name'])
222 223
224 - def create_spin(self, event):
225 """Wrapper method. 226 227 @param event: The wx event. 228 @type event: wx event 229 """ 230 231 # Set up the user functions. 232 user_functions = User_functions(self.gui.spin_viewer) 233 234 # Call the dialog. 235 user_functions.spin.create(mol_name=self.info['mol_name'], res_num=self.info['res_num'], res_name=self.info['res_name'])
236 237
238 - def delete_molecule(self, event):
239 """Wrapper method. 240 241 @param event: The wx event. 242 @type event: wx event 243 """ 244 245 # Ask if this should be done. 246 msg = "Are you sure you would like to delete this molecule? This only affects the spin data, all structural data will remain. This operation cannot be undone." 247 if status.show_gui and Question(msg, parent=self.gui.spin_viewer, default=False, size=(400, 170)).ShowModal() == wx.ID_NO: 248 return 249 250 # Delete the molecule. 251 self.gui.interpreter.queue('molecule.delete', gui_to_str(self.info['id'])) 252 253 # Notify all observers that a user function has completed. 254 status.observers.gui_uf.notify()
255 256
257 - def delete_residue(self, event):
258 """Wrapper method. 259 260 @param event: The wx event. 261 @type event: wx event 262 """ 263 264 # Ask if this should be done. 265 msg = "Are you sure you would like to delete this residue? This only affects the spin data, all structural data will remain. This operation cannot be undone." 266 if status.show_gui and Question(msg, parent=self.gui.spin_viewer, default=False, size=(400, 170)).ShowModal() == wx.ID_NO: 267 return 268 269 # Delete the residue. 270 self.gui.interpreter.queue('residue.delete', gui_to_str(self.info['id'])) 271 272 # Notify all observers that a user function has completed. 273 status.observers.gui_uf.notify()
274 275
276 - def delete_spin(self, event):
277 """Wrapper method. 278 279 @param event: The wx event. 280 @type event: wx event 281 """ 282 283 # Ask if this should be done. 284 msg = "Are you sure you would like to delete this spin? This only affects the spin data, all structural data will remain. This operation cannot be undone." 285 if status.show_gui and Question(msg, parent=self.gui.spin_viewer, default=False, size=(400, 170)).ShowModal() == wx.ID_NO: 286 return 287 288 # Delete the spin. 289 self.gui.interpreter.queue('spin.delete', gui_to_str(self.info['id'])) 290 291 # Notify all observers that a user function has completed. 292 status.observers.gui_uf.notify()
293 294
295 - def deselect_molecule(self, event):
296 """Wrapper method. 297 298 @param event: The wx event. 299 @type event: wx event 300 """ 301 302 # Ask if this should be done. 303 msg = "Are you sure you would like to deselect all spins of this molecule?" 304 if status.show_gui and Question(msg, parent=self.gui.spin_viewer, default=False).ShowModal() == wx.ID_NO: 305 return 306 307 # Deselect the molecule. 308 self.gui.interpreter.queue('deselect.spin', spin_id=gui_to_str(self.info['id']), change_all=False) 309 310 # Notify all observers that a user function has completed. 311 status.observers.gui_uf.notify()
312 313
314 - def deselect_residue(self, event):
315 """Wrapper method. 316 317 @param event: The wx event. 318 @type event: wx event 319 """ 320 321 # Ask if this should be done. 322 msg = "Are you sure you would like to deselect all spins of this residue?" 323 if status.show_gui and Question(msg, parent=self.gui.spin_viewer, default=False).ShowModal() == wx.ID_NO: 324 return 325 326 # Deselect the residue. 327 self.gui.interpreter.queue('deselect.spin', spin_id=gui_to_str(self.info['id']), change_all=False) 328 329 # Notify all observers that a user function has completed. 330 status.observers.gui_uf.notify()
331 332
333 - def deselect_spin(self, event):
334 """Wrapper method. 335 336 @param event: The wx event. 337 @type event: wx event 338 """ 339 340 # Deselect the spin. 341 self.gui.interpreter.queue('deselect.spin', spin_id=gui_to_str(self.info['id']), change_all=False) 342 343 # Notify all observers that a user function has completed. 344 status.observers.gui_uf.notify()
345 346
347 - def get_info(self):
348 """Get the python data structure associated with the current item. 349 350 @return: The dictionary of data. 351 @rtype: dict 352 """ 353 354 # The current item. 355 item = self.tree.GetSelection() 356 357 # No data. 358 if not item.IsOk(): 359 return 360 361 # Return the associated python data. 362 return self.tree.GetItemPyData(item)
363 364
365 - def menu_default(self):
366 """The right click root menu.""" 367 368 # The menu. 369 menu = wx.Menu() 370 371 # The load spins entry. 372 item = build_menu_item(menu, id=self.MENU_ROOT_LOAD_SPINS, text="Load spins", icon=paths.icon_16x16.spin) 373 menu.AppendItem(item) 374 if status.exec_lock.locked(): 375 item.Enable(False) 376 377 # The menu actions. 378 self.Bind(wx.EVT_MENU, self.gui.spin_viewer.load_spins_wizard, id=self.MENU_ROOT_LOAD_SPINS) 379 380 # Show the menu. 381 if status.show_gui: 382 self.PopupMenu(menu) 383 menu.Destroy()
384 385
386 - def menu_molecule(self):
387 """The right click molecule menu.""" 388 389 # The menu. 390 menu = wx.Menu() 391 item = build_menu_item(menu, id=self.MENU_MOLECULE_RESIDUE_CREATE, text="Add residue", icon=paths.icon_16x16.add) 392 menu.AppendItem(item) 393 if status.exec_lock.locked(): 394 item.Enable(False) 395 item = build_menu_item(menu, id=self.MENU_MOLECULE_MOLECULE_DELETE, text="Delete molecule", icon=paths.icon_16x16.remove) 396 menu.AppendItem(item) 397 if status.exec_lock.locked(): 398 item.Enable(False) 399 400 # Selection or deselection. 401 if self.info['select']: 402 item = build_menu_item(menu, id=self.MENU_MOLECULE_MOLECULE_DESELECT, text="Deselect") 403 menu.AppendItem(item) 404 if status.exec_lock.locked(): 405 item.Enable(False) 406 else: 407 item = build_menu_item(menu, id=self.MENU_MOLECULE_MOLECULE_SELECT, text="Select") 408 menu.AppendItem(item) 409 if status.exec_lock.locked(): 410 item.Enable(False) 411 412 # The menu actions. 413 self.Bind(wx.EVT_MENU, self.create_residue, id=self.MENU_MOLECULE_RESIDUE_CREATE) 414 self.Bind(wx.EVT_MENU, self.delete_molecule, id=self.MENU_MOLECULE_MOLECULE_DELETE) 415 if self.info['select']: 416 self.Bind(wx.EVT_MENU, self.deselect_molecule, id=self.MENU_MOLECULE_MOLECULE_DESELECT) 417 else: 418 self.Bind(wx.EVT_MENU, self.select_molecule, id=self.MENU_MOLECULE_MOLECULE_SELECT) 419 420 # Show the menu. 421 if status.show_gui: 422 self.PopupMenu(menu) 423 menu.Destroy()
424 425
426 - def menu_residue(self):
427 """The right click molecule menu.""" 428 429 # The menu. 430 menu = wx.Menu() 431 item = build_menu_item(menu, id=self.MENU_RESIDUE_SPIN_ADD, text="Add spin", icon=paths.icon_16x16.add) 432 menu.AppendItem(item) 433 if status.exec_lock.locked(): 434 item.Enable(False) 435 item = build_menu_item(menu, id=self.MENU_RESIDUE_RESIDUE_DELETE, text="Delete residue", icon=paths.icon_16x16.remove) 436 menu.AppendItem(item) 437 if status.exec_lock.locked(): 438 item.Enable(False) 439 440 # Selection or deselection. 441 if self.info['select']: 442 item = build_menu_item(menu, id=self.MENU_RESIDUE_RESIDUE_DESELECT, text="Deselect") 443 menu.AppendItem(item) 444 if status.exec_lock.locked(): 445 item.Enable(False) 446 else: 447 item = build_menu_item(menu, id=self.MENU_RESIDUE_RESIDUE_SELECT, text="Select") 448 menu.AppendItem(item) 449 if status.exec_lock.locked(): 450 item.Enable(False) 451 452 # The menu actions. 453 self.Bind(wx.EVT_MENU, self.create_spin, id=self.MENU_RESIDUE_SPIN_ADD) 454 self.Bind(wx.EVT_MENU, self.delete_residue, id=self.MENU_RESIDUE_RESIDUE_DELETE) 455 if self.info['select']: 456 self.Bind(wx.EVT_MENU, self.deselect_residue, id=self.MENU_RESIDUE_RESIDUE_DESELECT) 457 else: 458 self.Bind(wx.EVT_MENU, self.select_residue, id=self.MENU_RESIDUE_RESIDUE_SELECT) 459 460 # Show the menu. 461 if status.show_gui: 462 self.PopupMenu(menu) 463 menu.Destroy()
464 465
466 - def menu_root(self):
467 """The right click root menu.""" 468 469 # The menu. 470 menu = wx.Menu() 471 472 # The add molecule entry. 473 item = build_menu_item(menu, id=self.MENU_ROOT_MOLECULE_CREATE, text="Add molecule", icon=paths.icon_16x16.add) 474 menu.AppendItem(item) 475 if status.exec_lock.locked(): 476 item.Enable(False) 477 478 # The add molecule entry. 479 item = build_menu_item(menu, id=self.MENU_ROOT_LOAD_SPINS, text="Load spins", icon=paths.icon_16x16.spin) 480 menu.AppendItem(item) 481 if status.exec_lock.locked(): 482 item.Enable(False) 483 484 # The menu actions. 485 self.Bind(wx.EVT_MENU, self.create_molecule, id=self.MENU_ROOT_MOLECULE_CREATE) 486 self.Bind(wx.EVT_MENU, self.gui.spin_viewer.load_spins_wizard, id=self.MENU_ROOT_LOAD_SPINS) 487 488 # Show the menu. 489 if status.show_gui: 490 self.PopupMenu(menu) 491 menu.Destroy()
492 493
494 - def menu_spin(self):
495 """The right click spin menu.""" 496 497 # The menu. 498 menu = wx.Menu() 499 item = build_menu_item(menu, id=self.MENU_SPIN_SPIN_DELETE, text="Delete spin", icon=paths.icon_16x16.remove) 500 menu.AppendItem(item) 501 if status.exec_lock.locked(): 502 item.Enable(False) 503 504 # Selection or deselection. 505 if self.info['select']: 506 item = build_menu_item(menu, id=self.MENU_SPIN_SPIN_DESELECT, text="Deselect") 507 menu.AppendItem(item) 508 if status.exec_lock.locked(): 509 item.Enable(False) 510 else: 511 item = build_menu_item(menu, id=self.MENU_SPIN_SPIN_SELECT, text="Select") 512 menu.AppendItem(item) 513 if status.exec_lock.locked(): 514 item.Enable(False) 515 516 # The menu actions. 517 self.Bind(wx.EVT_MENU, self.delete_spin, id=self.MENU_SPIN_SPIN_DELETE) 518 if self.info['select']: 519 self.Bind(wx.EVT_MENU, self.deselect_spin, id=self.MENU_SPIN_SPIN_DESELECT) 520 else: 521 self.Bind(wx.EVT_MENU, self.select_spin, id=self.MENU_SPIN_SPIN_SELECT) 522 523 # Show the menu. 524 if status.show_gui: 525 self.PopupMenu(menu) 526 menu.Destroy()
527 528
529 - def prune_mol(self):
530 """Remove any molecules which have been deleted.""" 531 532 # Get a list of molecule IDs from the relax data store. 533 mol_ids = get_molecule_ids() 534 535 # Find if the molecule has been removed. 536 prune_list = [] 537 for key in self.tree_ids.keys(): 538 # Get the python data. 539 info = self.tree.GetItemPyData(key) 540 541 # Prune if it has been removed. 542 if info['id'] not in mol_ids: 543 self.tree.Delete(key) 544 self.tree_ids.pop(key)
545 546
547 - def prune_res(self, mol_branch_id, mol_id):
548 """Remove any molecules which have been deleted. 549 550 @param mol_branch_id: The molecule branch ID of the wx.TreeCtrl object. 551 @type mol_branch_id: TreeItemId 552 @param mol_id: The molecule identification string. 553 @type mol_id: str 554 """ 555 556 # Get a list of residue IDs from the relax data store. 557 res_ids = get_residue_ids(mol_id) 558 559 # Find if the molecule has been removed. 560 prune_list = [] 561 for key in self.tree_ids[mol_branch_id].keys(): 562 # Get the python data. 563 info = self.tree.GetItemPyData(key) 564 565 # Prune if it has been removed. 566 if info['id'] not in res_ids: 567 self.tree.Delete(key) 568 self.tree_ids[mol_branch_id].pop(key)
569 570
571 - def prune_spin(self, mol_branch_id, res_branch_id, res_id):
572 """Remove any spins which have been deleted. 573 574 @param mol_branch_id: The molecule branch ID of the wx.TreeCtrl object. 575 @type mol_branch_id: TreeItemId 576 @param res_branch_id: The residue branch ID of the wx.TreeCtrl object. 577 @type res_branch_id: TreeItemId 578 @param res_id: The residue identification string. 579 @type res_id: str 580 """ 581 582 # Get a list of spin IDs from the relax data store. 583 spin_ids = get_spin_ids(res_id) 584 585 # Find if the molecule has been removed. 586 prune_list = [] 587 for key in self.tree_ids[mol_branch_id][res_branch_id].keys(): 588 # Get the python data. 589 info = self.tree.GetItemPyData(key) 590 591 # Prune if it has been removed. 592 if info['id'] not in spin_ids: 593 self.tree.Delete(key) 594 self.tree_ids[mol_branch_id][res_branch_id].pop(key)
595 596
597 - def select_molecule(self, event):
598 """Wrapper method. 599 600 @param event: The wx event. 601 @type event: wx event 602 """ 603 604 # Ask if this should be done. 605 msg = "Are you sure you would like to select all spins of this molecule?" 606 if status.show_gui and Question(msg, parent=self.gui.spin_viewer, default=False).ShowModal() == wx.ID_NO: 607 return 608 609 # Select the molecule. 610 self.gui.interpreter.queue('select.spin', spin_id=gui_to_str(self.info['id']), change_all=False) 611 612 # Notify all observers that a user function has completed. 613 status.observers.gui_uf.notify()
614 615
616 - def select_residue(self, event):
617 """Wrapper method. 618 619 @param event: The wx event. 620 @type event: wx event 621 """ 622 623 # Ask if this should be done. 624 msg = "Are you sure you would like to select all spins of this residue?" 625 if status.show_gui and Question(msg, parent=self.gui.spin_viewer, default=False).ShowModal() == wx.ID_NO: 626 return 627 628 # Select the residue. 629 self.gui.interpreter.queue('select.spin', spin_id=gui_to_str(self.info['id']), change_all=False) 630 631 # Notify all observers that a user function has completed. 632 status.observers.gui_uf.notify()
633 634
635 - def select_spin(self, event):
636 """Wrapper method. 637 638 @param event: The wx event. 639 @type event: wx event 640 """ 641 642 # Select the spin. 643 self.gui.interpreter.queue('select.spin', spin_id=gui_to_str(self.info['id']), change_all=False) 644 645 # Notify all observers that a user function has completed. 646 status.observers.gui_uf.notify()
647 648
649 - def set_bitmap_mol(self, mol_branch_id, select=True):
650 """Set the molecule bitmaps. 651 652 @param mol_branch_id: The molecule branch ID of the wx.TreeCtrl object. 653 @type mol_branch_id: TreeItemId 654 @keyword select: The selection flag. 655 @type select: bool 656 """ 657 658 # The bitmaps for the selected state. 659 if select: 660 bmp = self.icon_mol_index 661 bmp_unfold = self.icon_mol_unfold_index 662 663 # The bitmaps for the deselected state. 664 else: 665 bmp = self.icon_mol_index_desel 666 bmp_unfold = self.icon_mol_unfold_index_desel 667 668 # Set the image. 669 self.tree.SetItemImage(mol_branch_id, bmp, wx.TreeItemIcon_Normal) 670 self.tree.SetItemImage(mol_branch_id, bmp_unfold, wx.TreeItemIcon_Expanded)
671 672
673 - def set_bitmap_res(self, res_branch_id, select=True):
674 """Set the residue bitmaps. 675 676 @param res_branch_id: The residue branch ID of the wx.TreeCtrl object. 677 @type res_branch_id: TreeItemId 678 @keyword select: The selection flag. 679 @type select: bool 680 """ 681 682 # The bitmaps for the selected state. 683 if select: 684 bmp = self.icon_res_index 685 686 # The bitmaps for the deselected state. 687 else: 688 bmp = self.icon_res_index_desel 689 690 # Set the image. 691 self.tree.SetItemImage(res_branch_id, bmp, wx.TreeItemIcon_Normal & wx.TreeItemIcon_Expanded)
692 693
694 - def set_bitmap_spin(self, spin_branch_id, select=True):
695 """Set the spin bitmaps. 696 697 @param spin_branch_id: The spin branch ID of the wx.TreeCtrl object. 698 @type spin_branch_id: TreeItemId 699 @keyword select: The selection flag. 700 @type select: bool 701 """ 702 703 # The bitmaps for the selected state. 704 if select: 705 bmp = self.icon_spin_index 706 707 # The bitmaps for the deselected state. 708 else: 709 bmp = self.icon_spin_index_desel 710 711 # Set the image. 712 self.tree.SetItemImage(spin_branch_id, bmp, wx.TreeItemIcon_Normal & wx.TreeItemIcon_Expanded)
713 714
715 - def update(self, pipe_name=None):
716 """Update the tree view using the given data pipe.""" 717 718 # Acquire the pipe and spin locks. 719 status.pipe_lock.acquire('spin viewer window') 720 status.spin_lock.acquire('spin viewer window') 721 try: 722 # The data pipe. 723 if not pipe_name: 724 pipe = cdp 725 else: 726 pipe = get_pipe(pipe_name) 727 728 # No data pipe, so delete everything and return. 729 if not pipe: 730 self.tree.DeleteChildren(self.root) 731 return 732 733 # Update the molecules. 734 for mol, mol_id in molecule_loop(return_id=True): 735 self.update_mol(mol, mol_id) 736 737 # Remove any deleted molecules. 738 self.prune_mol() 739 740 # Release the locks. 741 finally: 742 status.pipe_lock.release('spin viewer window') 743 status.spin_lock.release('spin viewer window')
744 745
746 - def update_mol(self, mol, mol_id):
747 """Update the given molecule in the tree. 748 749 @param mol: The molecule container. 750 @type mol: MoleculeContainer instance 751 @param mol_id: The molecule identification string. 752 @type mol_id: str 753 """ 754 755 # Find the molecule, if it already exists. 756 new_mol = True 757 for key in self.tree_ids.keys(): 758 # Get the python data. 759 data = self.tree.GetItemPyData(key) 760 761 # Check the mol_id for a match and, if so, terminate to speed things up. 762 if mol_id == data['id']: 763 new_mol = False 764 mol_branch_id = key 765 break 766 767 # A new molecule. 768 if new_mol: 769 # Append a molecule with name to the tree. 770 mol_branch_id = self.tree.AppendItem(self.root, "Molecule: %s" % mol.name) 771 772 # The data to store. 773 data = { 774 'type': 'mol', 775 'mol_name': mol.name, 776 'id': mol_id, 777 'select': is_mol_selected(mol_id) 778 } 779 self.tree.SetPyData(mol_branch_id, data) 780 781 # Add the id to the tracking structure. 782 self.tree_ids[mol_branch_id] = {} 783 784 # Set the bitmap. 785 self.set_bitmap_mol(mol_branch_id, select=data['select']) 786 787 # An old molecule. 788 else: 789 # Check the selection state. 790 select = is_mol_selected(data['id']) 791 792 # Change of state. 793 if select != data['select']: 794 # Store the new state. 795 data['select'] = select 796 797 # Set the bitmap. 798 self.set_bitmap_mol(mol_branch_id, select=data['select']) 799 800 # Update the residues of this molecule. 801 for res, res_id in residue_loop(mol_id, return_id=True): 802 self.update_res(mol_branch_id, mol, res, res_id) 803 804 # Start new molecules expanded. 805 if new_mol and data['select']: 806 self.tree.Expand(mol_branch_id) 807 808 # Remove any deleted residues. 809 self.prune_res(mol_branch_id, mol_id) 810 811 # Expand the root. 812 self.tree.Expand(self.root)
813 814
815 - def update_res(self, mol_branch_id, mol, res, res_id):
816 """Update the given residue in the tree. 817 818 @param mol_branch_id: The molecule branch ID of the wx.TreeCtrl object. 819 @type mol_branch_id: TreeItemId 820 @param mol: The molecule container. 821 @type mol: MoleculeContainer instance 822 @param res: The residue container. 823 @type res: ResidueContainer instance 824 @param res_id: The residue identification string. 825 @type res_id: str 826 """ 827 828 # Find the residue, if it already exists. 829 new_res = True 830 for key in self.tree_ids[mol_branch_id].keys(): 831 # Get the python data. 832 data = self.tree.GetItemPyData(key) 833 834 # Check the res_id for a match and, if so, terminate to speed things up. 835 if res_id == data['id']: 836 new_res = False 837 res_branch_id = key 838 break 839 840 # A new residue. 841 if new_res: 842 # Append a residue with name and number to the tree. 843 res_branch_id = self.tree.AppendItem(mol_branch_id, "Residue: %s %s" % (res.num, res.name)) 844 845 # The data to store. 846 data = { 847 'type': 'res', 848 'mol_name': mol.name, 849 'res_name': res.name, 850 'res_num': res.num, 851 'id': res_id, 852 'select': is_res_selected(res_id) 853 } 854 self.tree.SetPyData(res_branch_id, data) 855 856 # Add the id to the tracking structure. 857 self.tree_ids[mol_branch_id][res_branch_id] = {} 858 859 # Set the bitmap. 860 self.set_bitmap_res(res_branch_id, select=data['select']) 861 862 # An old residue. 863 else: 864 # Check the selection state. 865 select = is_res_selected(data['id']) 866 867 # Change of state. 868 if select != data['select']: 869 # Store the new state. 870 data['select'] = select 871 872 # Set the bitmap. 873 self.set_bitmap_res(res_branch_id, select=data['select']) 874 875 # Update the spins of this residue. 876 for spin, spin_id in spin_loop(res_id, return_id=True): 877 self.update_spin(mol_branch_id, res_branch_id, mol, res, spin, spin_id) 878 879 # Start new residues expanded. 880 if new_res and data['select']: 881 self.tree.Expand(res_branch_id) 882 883 # Remove any deleted spins. 884 self.prune_spin(mol_branch_id, res_branch_id, res_id)
885 886
887 - def update_spin(self, mol_branch_id, res_branch_id, mol, res, spin, spin_id):
888 """Update the given spin in the tree. 889 890 @param mol_branch_id: The molecule branch ID of the wx.TreeCtrl object. 891 @type mol_branch_id: TreeItemId 892 @param res_branch_id: The residue branch ID of the wx.TreeCtrl object. 893 @type res_branch_id: TreeItemId 894 @param mol: The molecule container. 895 @type mol: MoleculeContainer instance 896 @param res: The residue container. 897 @type res: ResidueContainer instance 898 @param spin: The spin container. 899 @type spin: SpinContainer instance 900 @param spin_id: The spin identification string. 901 @type spin_id: str 902 """ 903 904 # Find the spin, if it already exists. 905 new_spin = True 906 for key in self.tree_ids[mol_branch_id][res_branch_id].keys(): 907 # Get the python data. 908 data = self.tree.GetItemPyData(key) 909 910 # Check the spin_id for a match and, if so, terminate to speed things up. 911 if spin_id == data['id']: 912 new_spin = False 913 spin_branch_id = key 914 break 915 916 # A new spin. 917 if new_spin: 918 # Append a spin with name and number to the tree. 919 spin_branch_id = self.tree.AppendItem(res_branch_id, "Spin: %s %s" % (spin.num, spin.name)) 920 921 # The data to store. 922 data = { 923 'type': 'spin', 924 'mol_name': mol.name, 925 'res_name': res.name, 926 'res_num': res.num, 927 'spin_name': spin.name, 928 'spin_num': spin.num, 929 'id': spin_id, 930 'select': is_spin_selected(spin_id) 931 } 932 self.tree.SetPyData(spin_branch_id, data) 933 934 # Add the id to the tracking structure. 935 self.tree_ids[mol_branch_id][res_branch_id][spin_branch_id] = True 936 937 # Set the bitmap. 938 self.set_bitmap_spin(spin_branch_id, select=data['select']) 939 940 # An old spin. 941 else: 942 # Check the selection state. 943 select = is_spin_selected(data['id']) 944 945 # Change of state. 946 if select != data['select']: 947 # Store the new state. 948 data['select'] = select 949 950 # Set the bitmap. 951 self.set_bitmap_spin(spin_branch_id, select=data['select']) 952 953 # Start new spins expanded. 954 if new_spin and data['select']: 955 self.tree.Expand(spin_branch_id)
956