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 # Unset the mask if an alpha mask is detected (only on GNU/Linux and MS Windows). 131 if bitmap.HasAlpha() and not (hasattr(status, 'wx_info') and status.wx_info["os"] == "darwin"): 132 bitmap.SetMaskColour(wx.Colour(alpha=wx.ALPHA_OPAQUE)) 133 134 # Return the bitmap object. 135 return bitmap
136 137
138 -def format_table(table):
139 """Format the text by stripping whitespace. 140 141 @param table: The table. 142 @type table: lists of lists of str 143 @return: The formatted table. 144 @rtype: str 145 """ 146 147 # Initialise some variables. 148 text = '' 149 num_rows = len(table.cells) 150 num_cols = len(table.headings) 151 152 # The column widths. 153 widths = [] 154 for j in range(num_cols): 155 widths.append(len(table.headings[j])) 156 for i in range(num_rows): 157 for j in range(num_cols): 158 # The element is larger than the previous. 159 if len(table.cells[i][j]) > widths[j]: 160 widths[j] = len(table.cells[i][j]) 161 162 # The free space for the text. 163 used = 0 164 used += 2 # Start of the table ' '. 165 used += 2 # End of the table ' '. 166 used += 3 * (num_cols - 1) # Middle of the table ' '. 167 free_space = status.text_width - used 168 169 # The maximal width for all cells. 170 free_width = sum(widths) 171 172 # Column wrapping. 173 if free_width > free_space: 174 # New structures. 175 new_widths = deepcopy(widths) 176 num_cols_wrap = num_cols 177 free_space_wrap = free_space 178 col_wrap = [True] * num_cols 179 180 # Loop. 181 while True: 182 # The average column width. 183 ave_width = free_space_wrap / num_cols_wrap 184 185 # Rescale. 186 rescale = False 187 for i in range(num_cols): 188 # Remove the column from wrapping if smaller than the average wrapped width. 189 if col_wrap[i] and new_widths[i] < ave_width: 190 # Recalculate. 191 free_space_wrap = free_space_wrap - new_widths[i] 192 num_cols_wrap -= 1 193 rescale = True 194 195 # Remove the column from wrapping. 196 col_wrap[i] = False 197 198 # Done. 199 if not rescale: 200 # Set the column widths. 201 for i in range(num_cols): 202 if new_widths[i] > ave_width: 203 new_widths[i] = ave_width 204 break 205 206 # No column wrapping. 207 else: 208 new_widths = widths 209 col_wrap = [False] * num_cols 210 211 # The total table width. 212 total_width = sum(new_widths) + used 213 214 # The header. 215 text += " " + "_" * int(total_width - 2) + "\n\n" # Top rule and black line. 216 text += table_line(text=table.headings, widths=new_widths) # The headings. 217 text += table_line(widths=new_widths, bottom=True) # Middle rule. 218 219 # The table contents. 220 for i in range(num_rows): 221 # Column text, with wrapping. 222 col_text = [table.cells[i]] 223 num_lines = 1 224 for j in range(num_cols): 225 if col_wrap[j]: 226 # Wrap. 227 lines = wrap(col_text[0][j], new_widths[j]) 228 229 # Count the lines. 230 num_lines = len(lines) 231 232 # Replace the column text. 233 for k in range(num_lines): 234 # New row of empty text. 235 if len(col_text) <= k: 236 col_text.append(['']*num_cols) 237 238 # Pack the data. 239 col_text[k][j] = lines[k] 240 241 # Blank line (between rows when asked, and for the first row after the header). 242 if table.spacing or i == 1: 243 text += table_line(widths=new_widths) 244 245 # The contents. 246 for k in range(num_lines): 247 text += table_line(text=col_text[k], widths=new_widths) 248 249 # The bottom. 250 text += table_line(widths=new_widths, bottom=True) # Bottom rule. 251 252 # Add a newline. 253 text += '\n' 254 255 # Return the table text. 256 return text
257 258
259 -def open_file(file, force_text=False):
260 """Open the file in the platform's native editor/viewer. 261 262 @param file: The path of the file to open. 263 @type file: str 264 @keyword force_text: A flag which if True will cause a text editor to be launched. 265 @type force_text: bool 266 """ 267 268 # Windows. 269 if platform.uname()[0] in ['Windows', 'Microsoft']: 270 # Text file. 271 if force_text: 272 os.system("notepad '%s'" % os.path.normpath(file)) 273 274 # All other files. 275 else: 276 os.startfile(os.path.normpath(file)) 277 278 # Mac OS X. 279 elif platform.uname()[0] == 'Darwin': 280 # Text file. 281 if force_text: 282 os.system("open -t '%s'" % file) 283 284 # All other files. 285 else: 286 os.system("open '%s'" % file) 287 288 # POSIX Systems with xdg-open. 289 else: 290 os.system("/usr/bin/xdg-open '%s'" % file)
291 292
293 -def protected_exec(fn, *args, **kargs):
294 """Apply the given function, catching all RelaxErrors. 295 296 All args and keyword args supplied will be directly applied to the given function. 297 298 @param fn: The function to apply. 299 @type fn: func 300 @return: The status of execution. 301 @rtype: bool 302 """ 303 304 # Apply the function. 305 try: 306 fn(*args, **kargs) 307 308 # Catch RelaxErrors. 309 except AllRelaxErrors: 310 instance = sys.exc_info()[1] 311 312 # Raise the error in debugging mode. 313 if status.debug: 314 raise 315 316 # Display a dialog with the error. 317 gui_raise(instance, raise_flag=False) 318 319 # Failure. 320 return False 321 322 # Success. 323 return True
324 325
326 -def table_line(text=None, widths=None, bottom=False):
327 """Format a line of a table. 328 329 @keyword text: The list of table elements. If not given, an empty line will be be produced. 330 @type text: list of str or None 331 @keyword widths: The list of column widths for the table. 332 @type widths: list of int 333 @keyword botton: A flag which if True will cause a table bottom line to be produced. 334 @type bottom: bool 335 @return: The table line. 336 @rtype: str 337 """ 338 339 # Initialise. 340 if bottom: 341 line = " _" 342 else: 343 line = " " 344 345 # Loop over the columns. 346 for i in range(len(widths)): 347 # The column separator. 348 if i > 0: 349 if bottom: 350 line += "___" 351 else: 352 line += " " 353 354 # A bottom line. 355 if bottom: 356 line += "_" * int(widths[i]) 357 358 # Empty line. 359 elif text == None: 360 line += " " * int(widths[i]) 361 362 # The text. 363 else: 364 line += text[i] 365 line += " " * int(widths[i] - len(text[i])) 366 367 # Close the line. 368 if bottom: 369 line += "_ \n" 370 else: 371 line += " \n" 372 373 # Return the text. 374 return line
375