Package gui :: Package components :: Module relax_data
[hide private]
[frames] | no frames]

Source Code for Module gui.components.relax_data

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2009-2011 Michael Bieri                                       # 
  4  # Copyright (C) 2010-2012 Edward d'Auvergne                                   # 
  5  #                                                                             # 
  6  # This file is part of the program relax.                                     # 
  7  #                                                                             # 
  8  # relax is free software; you can redistribute it and/or modify               # 
  9  # it under the terms of the GNU General Public License as published by        # 
 10  # the Free Software Foundation; either version 2 of the License, or           # 
 11  # (at your option) any later version.                                         # 
 12  #                                                                             # 
 13  # relax is distributed in the hope that it will be useful,                    # 
 14  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 16  # GNU General Public License for more details.                                # 
 17  #                                                                             # 
 18  # You should have received a copy of the GNU General Public License           # 
 19  # along with relax; if not, write to the Free Software                        # 
 20  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   # 
 21  #                                                                             # 
 22  ############################################################################### 
 23   
 24  # Module docstring. 
 25  """Module containing the classes for GUI components involving relaxation data.""" 
 26   
 27  # Python module imports. 
 28  import wx 
 29  import wx.lib.buttons 
 30   
 31  # relax module imports. 
 32  from status import Status; status = Status() 
 33   
 34  # relax GUI module imports. 
 35  from gui.components.menu import build_menu_item 
 36  from gui.fonts import font 
 37  from gui.misc import add_border, float_to_gui, gui_to_str, str_to_gui 
 38  from gui import paths 
 39  from gui.user_functions import User_functions; user_functions = User_functions() 
 40   
 41   
42 -class Relax_data_list:
43 """The GUI element for listing loaded relaxation data.""" 44
45 - def __init__(self, gui=None, parent=None, box=None, id=None, buttons=True):
46 """Build the relaxation data list GUI element. 47 48 @keyword gui: The main GUI object. 49 @type gui: wx.Frame instance 50 @keyword parent: The parent GUI element that this is to be attached to (the panel object). 51 @type parent: wx object 52 @keyword data: The data storage container. 53 @type data: class instance 54 @keyword box: The vertical box sizer to pack this GUI component into. 55 @type box: wx.BoxSizer instance 56 @keyword id: A unique identification string. This is used to register the update method with the GUI user function observer object. 57 @type id: str 58 @keyword buttons: A flag which if True will display the buttons at the top. 59 @type buttons: bool 60 """ 61 62 # Store the arguments. 63 self.gui = gui 64 self.parent = parent 65 66 # GUI variables. 67 self.spacing = 5 68 self.border = 5 69 self.height_buttons = 40 70 71 # First create a panel (to allow for tooltips on the buttons). 72 self.panel = wx.Panel(self.parent) 73 box.Add(self.panel, 0, wx.ALL|wx.EXPAND, 0) 74 75 # Add a sizer to the panel. 76 panel_sizer = wx.BoxSizer(wx.VERTICAL) 77 self.panel.SetSizer(panel_sizer) 78 79 # A static box to hold all the widgets, and its sizer. 80 stat_box = wx.StaticBox(self.panel, -1, "Relaxation data list") 81 stat_box.SetFont(font.subtitle) 82 sub_sizer = wx.StaticBoxSizer(stat_box, wx.VERTICAL) 83 84 # Add the sizer to the static box and the static box to the main box. 85 panel_sizer.Add(sub_sizer, 0, wx.ALL|wx.EXPAND, 0) 86 87 # Add a border. 88 box_centre = add_border(sub_sizer, border=self.border) 89 90 # Add buttons. 91 if buttons: 92 self.add_buttons(box_centre) 93 94 # Initialise the element. 95 box_centre.AddSpacer(self.spacing) 96 self.init_element(box_centre) 97 98 # Build the element. 99 self.build_element() 100 101 # Initialise observer name. 102 self.name = 'relaxation data list: %s' % id 103 104 # Register the element for updating when a user function completes. 105 self.observer_register()
106 107
108 - def Enable(self, enable=True):
109 """Enable or disable the element. 110 111 @keyword enable: The flag specifying if the element should be enabled or disabled. 112 @type enable: bool 113 """ 114 115 # Call buttons' methods. 116 self.button_add.Enable(enable) 117 self.button_delete.Enable(enable)
118 119
120 - def add_buttons(self, sizer):
121 """Add the buttons for peak list manipulation. 122 123 @param sizer: The sizer element to pack the buttons into. 124 @type sizer: wx.BoxSizer instance 125 """ 126 127 # Button Sizer 128 button_sizer = wx.BoxSizer(wx.HORIZONTAL) 129 sizer.Add(button_sizer, 0, wx.ALL|wx.EXPAND, 0) 130 131 # Add button. 132 self.button_add = wx.lib.buttons.ThemedGenBitmapTextButton(self.panel, -1, None, " Add") 133 self.button_add.SetBitmapLabel(wx.Bitmap(paths.icon_22x22.add, wx.BITMAP_TYPE_ANY)) 134 self.button_add.SetFont(font.normal) 135 self.button_add.SetSize((80, self.height_buttons)) 136 button_sizer.Add(self.button_add, 0, 0, 0) 137 self.gui.Bind(wx.EVT_BUTTON, self.relax_data_read, self.button_add) 138 self.button_add.SetToolTipString("Read relaxation data from a file.") 139 140 # Bruker button. 141 self.button_bruker = wx.lib.buttons.ThemedGenBitmapTextButton(self.panel, -1, None, " Add") 142 self.button_bruker.SetBitmapLabel(wx.Bitmap(paths.icon_22x22.bruker_add, wx.BITMAP_TYPE_ANY)) 143 self.button_bruker.SetFont(font.normal) 144 self.button_bruker.SetSize((80, self.height_buttons)) 145 button_sizer.Add(self.button_bruker, 0, 0, 0) 146 self.gui.Bind(wx.EVT_BUTTON, self.bruker_read, self.button_bruker) 147 self.button_bruker.SetToolTipString("Read a Bruker Dynamics Center relaxation data file.") 148 149 # Delete button. 150 self.button_delete = wx.lib.buttons.ThemedGenBitmapTextButton(self.panel, -1, None, " Delete") 151 self.button_delete.SetBitmapLabel(wx.Bitmap(paths.icon_22x22.list_remove, wx.BITMAP_TYPE_ANY)) 152 self.button_delete.SetFont(font.normal) 153 self.button_delete.SetSize((80, self.height_buttons)) 154 button_sizer.Add(self.button_delete, 0, 0, 0) 155 self.gui.Bind(wx.EVT_BUTTON, self.relax_data_delete, self.button_delete) 156 self.button_delete.SetToolTipString("Delete loaded relaxation data from the relax data store.")
157 158
159 - def bruker_read(self, event):
160 """Launch the bruker.read user function. 161 162 @param event: The wx event. 163 @type event: wx event 164 """ 165 166 # Launch the dialog. 167 user_functions.bruker.read()
168 169
170 - def build_element(self):
171 """Build the relaxation data listing grid.""" 172 173 # Execution lock, so do nothing. 174 if status.exec_lock.locked(): 175 return 176 177 # Build the GUI element in a thread safe way. 178 wx.CallAfter(self.build_element_safe)
179 180
181 - def build_element_safe(self):
182 """Build the spectra listing GUI element in a thread safe wx.CallAfter call.""" 183 184 # First freeze the element, so that the GUI element doesn't update until the end. 185 self.element.Freeze() 186 187 # Delete the previous data. 188 self.element.DeleteAllItems() 189 190 # Expand the number of rows to match the number of relaxation IDs, and add the IDs. 191 n = 0 192 if hasattr(cdp, 'ri_ids'): 193 # The number of IDs. 194 n = len(cdp.ri_ids) 195 196 # Add all the data. 197 for i in range(n): 198 # Set the IDs. 199 id = cdp.ri_ids[i] 200 self.element.InsertStringItem(i, str_to_gui(id)) 201 202 # Set the data types. 203 self.element.SetStringItem(i, 1, str_to_gui(cdp.ri_type[id])) 204 205 # Set the frequencies. 206 self.element.SetStringItem(i, 2, float_to_gui(cdp.frq[id])) 207 208 # Size the columns. 209 self.size_cols() 210 211 # Post a size event to get the scroll panel to update correctly. 212 event = wx.PyCommandEvent(wx.EVT_SIZE.typeId, self.parent.GetId()) 213 wx.PostEvent(self.parent.GetEventHandler(), event) 214 215 # Set the minimum height. 216 head = self.height_char + 10 217 centre = (self.height_char + 6) * n 218 foot = wx.SystemSettings_GetMetric(wx.SYS_HSCROLL_Y) 219 height = head + centre + foot 220 self.element.SetMinSize((-1, height)) 221 self.element.Layout() 222 223 # Unfreeze. 224 self.element.Thaw()
225 226
227 - def delete(self):
228 """Unregister the class.""" 229 230 # Unregister the observer methods. 231 self.observer_register(remove=True)
232 233
234 - def init_element(self, sizer):
235 """Initialise the GUI element for the relaxation data listing. 236 237 @param sizer: The sizer element to pack the element into. 238 @type sizer: wx.BoxSizer instance 239 """ 240 241 # List of relaxation data. 242 self.element = wx.ListCtrl(self.panel, -1, style=wx.BORDER_SUNKEN|wx.LC_REPORT) 243 244 # Initialise to 3 columns. 245 self.element.InsertColumn(0, str_to_gui("Relaxation data ID")) 246 self.element.InsertColumn(1, str_to_gui("Data type")) 247 self.element.InsertColumn(2, str_to_gui("Frequency (Hz)")) 248 249 # Properties. 250 self.element.SetFont(font.normal) 251 252 # Store the base heights. 253 self.height_char = self.element.GetCharHeight() 254 255 # Bind some events. 256 self.element.Bind(wx.EVT_SIZE, self.resize) 257 self.element.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.on_right_click) # For wxMSW! 258 self.element.Bind(wx.EVT_RIGHT_UP, self.on_right_click) # For wxGTK! 259 260 # Add list to sizer. 261 sizer.Add(self.element, 0, wx.ALL|wx.EXPAND, 0)
262 263
264 - def observer_register(self, remove=False):
265 """Register and unregister methods with the observer objects. 266 267 @keyword remove: If set to True, then the methods will be unregistered. 268 @type remove: False 269 """ 270 271 # Register. 272 if not remove: 273 status.observers.gui_uf.register(self.name, self.build_element) 274 275 # Unregister. 276 else: 277 status.observers.gui_uf.unregister(self.name)
278 279
280 - def on_right_click(self, event):
281 """Pop up menu for the right click. 282 283 @param event: The wx event. 284 @type event: wx event 285 """ 286 287 # Execution lock, so do nothing. 288 if status.exec_lock.locked(): 289 return 290 291 # New menu entry. 292 if not hasattr(self, 'popup_id_del'): 293 # ID number. 294 self.popup_id_del = wx.NewId() 295 296 # Bind clicks. 297 self.element.Bind(wx.EVT_MENU, self.relax_data_delete, id=self.popup_id_del) 298 299 # Initialise the menu. 300 menu = wx.Menu() 301 302 # Add the delete entry. 303 menu.AppendItem(build_menu_item(menu, id=self.popup_id_del, text="&Delete", icon=paths.icon_16x16.remove)) 304 305 # Pop up the menu. 306 self.element.PopupMenu(menu) 307 menu.Destroy()
308 309
310 - def relax_data_delete(self, event):
311 """Launch the relax_data.delete user function. 312 313 @param event: The wx event. 314 @type event: wx event 315 """ 316 317 # The current selection. 318 item = self.element.GetFirstSelected() 319 320 # No selection. 321 if item == -1: 322 id = None 323 324 # Selected item. 325 else: 326 # The spectrum ID. 327 id = gui_to_str(self.element.GetItemText(item)) 328 329 # Launch the dialog. 330 user_functions.relax_data.delete(ri_id=id)
331 332
333 - def relax_data_read(self, event):
334 """Launch the relax_data.read user function. 335 336 @param event: The wx event. 337 @type event: wx event 338 """ 339 340 # Launch the dialog. 341 user_functions.relax_data.read()
342 343
344 - def resize(self, event):
345 """Catch the resize to allow the element to be resized. 346 347 @param event: The wx event. 348 @type event: wx event 349 """ 350 351 # Set the column sizes. 352 self.size_cols() 353 354 # Continue with the normal resizing. 355 event.Skip()
356 357
358 - def size_cols(self):
359 """Set the column sizes.""" 360 361 # The element size. 362 x, y = self.element.GetSize() 363 364 # Number of columns. 365 n = self.element.GetColumnCount() 366 367 # Set to equal sizes. 368 if n == 0: 369 width = x 370 else: 371 width = int(x / n) 372 373 # Set the column sizes. 374 for i in range(n): 375 self.element.SetColumnWidth(i, width)
376