Package gui :: Module misc
[hide private]
[frames] | no frames]

Source Code for Module gui.misc

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2009-2010 Michael Bieri                                       # 
  4  # Copyright (C) 2009-2012 Edward d'Auvergne                                   # 
  5  #                                                                             # 
  6  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  7  #                                                                             # 
  8  # This program 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 3 of the License, or           # 
 11  # (at your option) any later version.                                         # 
 12  #                                                                             # 
 13  # This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 20  #                                                                             # 
 21  ############################################################################### 
 22   
 23  # Module docstring. 
 24  """Miscellaneous functions used throughout the GUI.""" 
 25   
 26  # Python module imports. 
 27  from copy import deepcopy 
 28  import os 
 29  import platform 
 30  import sys 
 31  from textwrap import wrap 
 32  import wx 
 33   
 34  # relax module imports. 
 35  from gui.errors import gui_raise 
 36  from lib.errors import AllRelaxErrors 
 37  from status import Status; status = Status() 
 38   
 39   
40 -def add_border(box, border=0, packing=wx.VERTICAL, debug=False):
41 """Create the main part of the frame, returning the central sizer. 42 43 @param box: The box sizer element to pack the borders into. 44 @type box: wx.BoxSizer instance 45 @keyword border: The size of the border in pixels. 46 @type border: int 47 @keyword packing: Specify if the central sizer should be vertically or horizontally packed. 48 @type packing: wx.VERTICAL or wx.HORIZONTAL 49 @keyword debug: A flag which if true will make colourful borders. 50 @type debug: bool 51 @return: The central sizer. 52 @rtype: wx.BoxSizer instance 53 """ 54 55 # The orientation of the sub sizer. 56 orient = box.GetOrientation() 57 if orient == wx.HORIZONTAL: 58 orient_sub = wx.VERTICAL 59 else: 60 orient_sub = wx.HORIZONTAL 61 62 # Some sizers. 63 sizer_sub = wx.BoxSizer(orient_sub) 64 sizer_cent = wx.BoxSizer(packing) 65 66 # Left and right borders (debugging). 67 if debug: 68 # Left coloured panel. 69 panel = wx.Panel(box.GetContainingWindow(), -1) 70 panel.SetSize((border, border)) 71 panel.SetBackgroundColour("Red") 72 box.Add(panel, 0, wx.EXPAND|wx.ALL) 73 74 # Centre. 75 box.Add(sizer_sub, 1, wx.EXPAND|wx.ALL) 76 77 # Top coloured panel. 78 panel = wx.Panel(box.GetContainingWindow(), -1) 79 panel.SetSize((border, border)) 80 panel.SetBackgroundColour("Yellow") 81 box.Add(panel, 0, wx.EXPAND|wx.ALL) 82 83 # Left and right borders. 84 else: 85 box.AddSpacer(border) 86 box.Add(sizer_sub, 1, wx.EXPAND|wx.ALL) 87 box.AddSpacer(border) 88 89 # Top and bottom borders (debugging). 90 if debug: 91 # Top coloured panel. 92 panel = wx.Panel(box.GetContainingWindow(), -1) 93 panel.SetSize((border, border)) 94 panel.SetBackgroundColour("Blue") 95 sizer_sub.Add(panel, 0, wx.EXPAND|wx.ALL) 96 97 # Centre. 98 sizer_sub.Add(sizer_cent, 1, wx.EXPAND|wx.ALL) 99 100 # Bottom coloured panel. 101 panel = wx.Panel(box.GetContainingWindow(), -1) 102 panel.SetSize((border, border)) 103 panel.SetBackgroundColour("Green") 104 sizer_sub.Add(panel, 0, wx.EXPAND|wx.ALL) 105 106 # Top and bottom borders. 107 else: 108 sizer_sub.AddSpacer(border) 109 sizer_sub.Add(sizer_cent, 1, wx.EXPAND|wx.ALL) 110 sizer_sub.AddSpacer(border) 111 112 # Return the central sizer. 113 return sizer_cent
114 115
116 -def bitmap_setup(path):
117 """Build and return the bitmap, handling transparency for all operating systems. 118 119 This function is required to handle alpha in bitmap on MS Windows so that regions with partial transparency are not blended into the default dark grey colour of Windows' windows. 120 121 @param path: The absolute path to the bitmap image. 122 @type path: str 123 @return: The processed bitmap object. 124 @rtype: wx.Bitmap instance 125 """ 126 127 # Create the bitmap object. 128 bitmap = wx.Bitmap(path, wx.BITMAP_TYPE_ANY) 129 130 # Return the bitmap object. 131 return bitmap
132 133
134 -def format_table(table):
135 """Format the text by stripping whitespace. 136 137 @param table: The table. 138 @type table: lists of lists of str 139 @return: The formatted table. 140 @rtype: str 141 """ 142 143 # Initialise some variables. 144 text = '' 145 num_rows = len(table.cells) 146 num_cols = len(table.headings) 147 148 # The column widths. 149 widths = [] 150 for j in range(num_cols): 151 widths.append(len(table.headings[j])) 152 for i in range(num_rows): 153 for j in range(num_cols): 154 # The element is larger than the previous. 155 if len(table.cells[i][j]) > widths[j]: 156 widths[j] = len(table.cells[i][j]) 157 158 # The free space for the text. 159 used = 0 160 used += 2 # Start of the table ' '. 161 used += 2 # End of the table ' '. 162 used += 3 * (num_cols - 1) # Middle of the table ' '. 163 free_space = status.text_width - used 164 165 # The maximal width for all cells. 166 free_width = sum(widths) 167 168 # Column wrapping. 169 if free_width > free_space: 170 # New structures. 171 new_widths = deepcopy(widths) 172 num_cols_wrap = num_cols 173 free_space_wrap = free_space 174 col_wrap = [True] * num_cols 175 176 # Loop. 177 while True: 178 # The average column width. 179 ave_width = free_space_wrap / num_cols_wrap 180 181 # Rescale. 182 rescale = False 183 for i in range(num_cols): 184 # Remove the column from wrapping if smaller than the average wrapped width. 185 if col_wrap[i] and new_widths[i] < ave_width: 186 # Recalculate. 187 free_space_wrap = free_space_wrap - new_widths[i] 188 num_cols_wrap -= 1 189 rescale = True 190 191 # Remove the column from wrapping. 192 col_wrap[i] = False 193 194 # Done. 195 if not rescale: 196 # Set the column widths. 197 for i in range(num_cols): 198 if new_widths[i] > ave_width: 199 new_widths[i] = ave_width 200 break 201 202 # No column wrapping. 203 else: 204 new_widths = widths 205 col_wrap = [False] * num_cols 206 207 # The total table width. 208 total_width = sum(new_widths) + used 209 210 # The header. 211 text += " " + "_" * int(total_width - 2) + "\n\n" # Top rule and black line. 212 text += table_line(text=table.headings, widths=new_widths) # The headings. 213 text += table_line(widths=new_widths, bottom=True) # Middle rule. 214 215 # The table contents. 216 for i in range(num_rows): 217 # Column text, with wrapping. 218 col_text = [table.cells[i]] 219 num_lines = 1 220 for j in range(num_cols): 221 if col_wrap[j]: 222 # Wrap. 223 lines = wrap(col_text[0][j], new_widths[j]) 224 225 # Count the lines. 226 num_lines = len(lines) 227 228 # Replace the column text. 229 for k in range(num_lines): 230 # New row of empty text. 231 if len(col_text) <= k: 232 col_text.append(['']*num_cols) 233 234 # Pack the data. 235 col_text[k][j] = lines[k] 236 237 # Blank line (between rows when asked, and for the first row after the header). 238 if table.spacing or i == 1: 239 text += table_line(widths=new_widths) 240 241 # The contents. 242 for k in range(num_lines): 243 text += table_line(text=col_text[k], widths=new_widths) 244 245 # The bottom. 246 text += table_line(widths=new_widths, bottom=True) # Bottom rule. 247 248 # Add a newline. 249 text += '\n' 250 251 # Return the table text. 252 return text
253 254
255 -def open_file(file, force_text=False):
256 """Open the file in the platform's native editor/viewer. 257 258 @param file: The path of the file to open. 259 @type file: str 260 @keyword force_text: A flag which if True will cause a text editor to be launched. 261 @type force_text: bool 262 """ 263 264 # Windows. 265 if platform.uname()[0] in ['Windows', 'Microsoft']: 266 # Text file. 267 if force_text: 268 os.system("notepad '%s'" % os.path.normpath(file)) 269 270 # All other files. 271 else: 272 os.startfile(os.path.normpath(file)) 273 274 # Mac OS X. 275 elif platform.uname()[0] == 'Darwin': 276 # Text file. 277 if force_text: 278 os.system("open -t '%s'" % file) 279 280 # All other files. 281 else: 282 os.system("open '%s'" % file) 283 284 # POSIX Systems with xdg-open. 285 else: 286 os.system("/usr/bin/xdg-open '%s'" % file)
287 288
289 -def protected_exec(fn, *args, **kargs):
290 """Apply the given function, catching all RelaxErrors. 291 292 All args and keyword args supplied will be directly applied to the given function. 293 294 @param fn: The function to apply. 295 @type fn: func 296 @return: The status of execution. 297 @rtype: bool 298 """ 299 300 # Apply the function. 301 try: 302 fn(*args, **kargs) 303 304 # Catch RelaxErrors. 305 except AllRelaxErrors: 306 instance = sys.exc_info()[1] 307 308 # Raise the error in debugging mode. 309 if status.debug: 310 raise 311 312 # Display a dialog with the error. 313 gui_raise(instance, raise_flag=False) 314 315 # Failure. 316 return False 317 318 # Success. 319 return True
320 321
322 -def table_line(text=None, widths=None, bottom=False):
323 """Format a line of a table. 324 325 @keyword text: The list of table elements. If not given, an empty line will be be produced. 326 @type text: list of str or None 327 @keyword widths: The list of column widths for the table. 328 @type widths: list of int 329 @keyword botton: A flag which if True will cause a table bottom line to be produced. 330 @type bottom: bool 331 @return: The table line. 332 @rtype: str 333 """ 334 335 # Initialise. 336 if bottom: 337 line = " _" 338 else: 339 line = " " 340 341 # Loop over the columns. 342 for i in range(len(widths)): 343 # The column separator. 344 if i > 0: 345 if bottom: 346 line += "___" 347 else: 348 line += " " 349 350 # A bottom line. 351 if bottom: 352 line += "_" * int(widths[i]) 353 354 # Empty line. 355 elif text == None: 356 line += " " * int(widths[i]) 357 358 # The text. 359 else: 360 line += text[i] 361 line += " " * int(widths[i] - len(text[i])) 362 363 # Close the line. 364 if bottom: 365 line += "_ \n" 366 else: 367 line += " \n" 368 369 # Return the text. 370 return line
371