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

Source Code for Module gui.misc

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