1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """The pipe editor GUI element."""
25
26
27 import wx
28
29
30 from data import Relax_data_store; ds = Relax_data_store()
31 from generic_fns.pipes import cdp_name, delete, get_type, pipe_names, switch
32 from status import Status; status = Status()
33
34
35 from gui.components.menu import build_menu_item
36 from gui.fonts import font
37 from gui.icons import relax_icons
38 from gui.message import Question
39 from gui.misc import add_border, gui_to_str, str_to_gui
40 from gui.paths import icon_16x16, icon_22x22, WIZARD_IMAGE_PATH
41 from gui.user_functions import User_functions
42
43
45 """The pipe editor window object."""
46
47 - def __init__(self, gui=None, size_x=800, size_y=500, border=10):
48 """Set up the relax controller frame.
49
50 @keyword gui: The main GUI object.
51 @type gui: wx.Frame instance
52 @keyword size_x: The initial and minimum width of the window.
53 @type size_x: int
54 @keyword size_y: The initial and minimum height of the window.
55 @type size_y: int
56 @keyword border: The size of the internal border of the window.
57 @type border: int
58 """
59
60
61 self.gui = gui
62 self.border = border
63
64
65 wx.Frame.__init__(self, None, id=-1, title="Data pipe editor")
66
67
68 self.user_functions = User_functions(self)
69
70
71 self.SetIcons(relax_icons)
72
73
74 self.width_col_label = 40
75
76
77 self.SetMinSize((size_x, size_y))
78 self.SetSize((size_x, size_y))
79
80
81 self.main_panel = wx.Panel(self, -1)
82
83
84 main_sizer = wx.BoxSizer(wx.VERTICAL)
85 self.main_panel.SetSizer(main_sizer)
86
87
88 sizer = add_border(main_sizer, border=border, packing=wx.VERTICAL)
89
90
91 sizer.AddSpacer(10)
92 self.add_logo(sizer)
93 sizer.AddSpacer(20)
94 self.add_buttons(sizer)
95 sizer.AddSpacer(10)
96 self.add_table(sizer)
97
98
99 self.grid.Bind(wx.EVT_SIZE, self.resize)
100 self.Bind(wx.EVT_CLOSE, self.handler_close)
101 self.grid.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK, self.menu)
102
103
104 self.name = 'pipe editor'
105
106
107 self.update_grid()
108
109
110 - def Show(self, show=True):
129
130
132 """Activate or deactivate certain elements in response to the execution lock."""
133
134
135 if status.exec_lock.locked():
136 wx.CallAfter(self.button_create.Enable, False)
137 wx.CallAfter(self.button_copy.Enable, False)
138 wx.CallAfter(self.button_delete.Enable, False)
139 wx.CallAfter(self.button_hybrid.Enable, False)
140 wx.CallAfter(self.button_switch.Enable, False)
141
142
143 else:
144 wx.CallAfter(self.button_create.Enable, True)
145 wx.CallAfter(self.button_copy.Enable, True)
146 wx.CallAfter(self.button_delete.Enable, True)
147 wx.CallAfter(self.button_hybrid.Enable, True)
148 wx.CallAfter(self.button_switch.Enable, True)
149
150
152 """The pop up menu.
153
154 @param event: The wx event.
155 @type event: wx event
156 """
157
158
159 row = event.GetRow()
160
161
162 self.selected_pipe = gui_to_str(self.grid.GetCellValue(row, 0))
163
164
165 if not self.selected_pipe:
166 return
167
168
169 pipe_type = get_type(self.selected_pipe)
170
171
172 menu = wx.Menu()
173
174
175 item = build_menu_item(menu, parent=self, text="&Delete the pipe", icon=icon_16x16.remove, fn=self.pipe_delete)
176 menu.AppendItem(item)
177 if status.exec_lock.locked():
178 item.Enable(False)
179
180
181 item = build_menu_item(menu, parent=self, text="&Switch to this pipe", icon=icon_16x16.pipe_switch, fn=self.pipe_switch)
182 menu.AppendItem(item)
183 if status.exec_lock.locked():
184 item.Enable(False)
185
186
187 if self.gui.analysis.page_index_from_pipe(self.selected_pipe) == None and pipe_type in ['noe', 'r1', 'r2', 'mf']:
188 item = build_menu_item(menu, parent=self, text="&Associate with a new auto-analysis", icon=icon_16x16.new, fn=self.associate_auto)
189 menu.AppendItem(item)
190 if status.exec_lock.locked():
191 item.Enable(False)
192
193
194 if status.show_gui:
195 self.PopupMenu(menu)
196
197
198 menu.Destroy()
199
200
251
252
271
272
274 """Add the logo to the sizer.
275
276 @param box: The sizer element to pack the logo into.
277 @type box: wx.Sizer instance
278 """
279
280
281 logo = wx.StaticBitmap(self.main_panel, -1, wx.Bitmap(WIZARD_IMAGE_PATH+'pipe_200x90.png', wx.BITMAP_TYPE_ANY))
282
283
284 box.Add(logo, 0, wx.ALIGN_CENTER_HORIZONTAL, 0)
285
286
288 """Add the table to the sizer.
289
290 @param sizer: The sizer element to pack the table into.
291 @type sizer: wx.Sizer instance
292 """
293
294
295 self.grid = wx.grid.Grid(self.main_panel, -1)
296
297
298 self.grid.CreateGrid(1, 4)
299
300
301 self.grid.SetColLabelValue(0, "Data pipe")
302 self.grid.SetColLabelValue(1, "Type")
303 self.grid.SetColLabelValue(2, "Current")
304 self.grid.SetColLabelValue(3, "Analysis tab")
305
306
307 self.grid.SetDefaultCellFont(font.normal)
308 self.grid.SetLabelFont(font.normal_bold)
309
310
311 self.grid.SetRowLabelSize(self.width_col_label)
312
313
314 self.grid.EnableDragColSize(False)
315 self.grid.EnableDragRowSize(False)
316
317
318 sizer.Add(self.grid, 1, wx.ALL|wx.EXPAND, 0)
319
320
322 """Associate the selected data pipe with a new auto-analysis.
323
324 @param event: The wx event.
325 @type event: wx event
326 """
327
328
329 if not hasattr(ds, 'relax_gui'):
330 self.gui.init_data()
331
332
333 type = get_type(self.selected_pipe)
334
335
336 names = {
337 'noe': 'Steady-state NOE',
338 'r1': 'R1 relaxation',
339 'r2': 'R2 relaxation',
340 'mf': 'Model-free'
341 }
342
343
344 self.gui.analysis.new_analysis(analysis_type=type, analysis_name=names[type], pipe_name=self.selected_pipe)
345
346
348 """Event handler for the close window action.
349
350 @param event: The wx event.
351 @type event: wx event
352 """
353
354
355 status.observers.pipe_alteration.unregister(self.name)
356 status.observers.gui_analysis.unregister(self.name)
357 status.observers.exec_lock.unregister(self.name)
358
359
360 self.Hide()
361
362
364 """Delete the date pipe.
365
366 @param event: The wx event.
367 @type event: wx event
368 """
369
370
371 msg = "Are you sure you would like to delete the '%s' data pipe? This operation cannot be undone." % self.selected_pipe
372 if status.show_gui and Question(msg, parent=self, default=False).ShowModal() == wx.ID_NO:
373 return
374
375
376 delete(self.selected_pipe)
377
378
380 """Switch to the selected date pipe.
381
382 @param event: The wx event.
383 @type event: wx event
384 """
385
386
387 switch(self.selected_pipe)
388
389
390 wx.CallAfter(self.Raise)
391
392
394 """Catch the resize to allow the grid to be resized.
395
396 @param event: The wx event.
397 @type event: wx event
398 """
399
400
401 self.size_cols()
402
403
404 event.Skip()
405
406
408 """Set the column sizes."""
409
410
411 x, y = self.grid.GetSize()
412
413
414 n = 4
415
416
417 width_col_curr = 80
418
419
420 width = int((x - self.width_col_label - width_col_curr) / (n - 1))
421
422
423 for i in range(n):
424
425 if i == 2:
426 self.grid.SetColSize(i, width_col_curr)
427
428
429 else:
430 self.grid.SetColSize(i, width)
431
432
434 """Update the grid in a thread safe way using wx.CallAfter."""
435
436
437 wx.CallAfter(self.update_grid_safe)
438
439
440 wx.GetApp().Yield(True)
441
442
444 """Update the grid with the pipe data."""
445
446
447 self.grid.Freeze()
448
449
450 status.pipe_lock.acquire('pipe editor window')
451
452
453 self.grid.DeleteRows(numRows=self.grid.GetNumberRows()-1)
454
455
456 for i in range(self.grid.GetNumberCols()):
457 self.grid.SetCellValue(0, i, str_to_gui(""))
458
459
460 pipe_list = pipe_names()
461 n = len(pipe_list)
462
463
464 if n >= 1:
465 self.grid.AppendRows(numRows=n-1)
466
467
468 for i in range(n):
469
470 self.grid.SetCellValue(i, 0, str_to_gui(pipe_list[i]))
471
472
473 self.grid.SetCellValue(i, 1, str_to_gui(get_type(pipe_list[i])))
474
475
476 if pipe_list[i] == cdp_name():
477 self.grid.SetCellValue(i, 2, str_to_gui("cdp"))
478
479
480 self.grid.SetCellValue(i, 3, str_to_gui(self.gui.analysis.page_name_from_pipe(pipe_list[i])))
481
482
483 for i in range(self.grid.GetNumberRows()):
484
485 self.grid.SetRowSize(i, 27)
486
487
488 for j in range(self.grid.GetNumberCols()):
489
490 self.grid.SetReadOnly(i, j)
491
492
493 status.pipe_lock.release('pipe editor window')
494
495
496 self.grid.Thaw()
497