1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """Module containing the base GUI element for listing things."""
25
26
27 import wx
28 import wx.lib.buttons
29
30
31 import dep_check
32 from gui.components.menu import build_menu_item
33 from gui.fonts import font
34 from gui.misc import add_border
35 from gui.string_conv import str_to_gui
36 from gui.uf_objects import Uf_storage; uf_store = Uf_storage()
37 from status import Status; status = Status()
38 from user_functions.data import Uf_info; uf_info = Uf_info()
39
40
42 """The GUI element for listing the software used in the analysis."""
43
44 - def __init__(self, gui=None, parent=None, box=None, id=None, proportion=0, button_placement='default'):
45 """Build the base list GUI element.
46
47 @keyword gui: The main GUI object.
48 @type gui: wx.Frame instance
49 @keyword parent: The parent GUI element that this is to be attached to.
50 @type parent: wx object
51 @keyword box: The box sizer to pack this GUI component into.
52 @type box: wx.BoxSizer instance
53 @keyword id: A unique identification string. This is used to register the update method with the GUI user function observer object.
54 @type id: str
55 @keyword proportion: The window proportion parameter.
56 @type proportion: bool
57 @keyword button_placement: Override the button visibility and placement. The value of 'default' will leave the buttons at the default setting. The value of 'top' will place the buttons at the top, 'bottom' will place them at the bottom, and None will turn off the buttons.
58 @type button_placement: str or None
59 """
60
61
62 self.gui = gui
63 self.parent = parent
64 self.proportion = proportion
65
66
67 self.title = ""
68 self.spacing = 5
69 self.border = 5
70 self.observer_base_name = None
71 self.columns = []
72 self.button_placement = None
73 self.button_size = (120, 40)
74 self.button_spacing = 5
75 self.button_info = []
76 self.popup_menus = []
77
78
79 self.setup()
80
81
82 if button_placement != 'default':
83 self.button_placement = button_placement
84
85
86 self.panel = wx.Panel(self.parent)
87 box.Add(self.panel, self.proportion, wx.ALL|wx.EXPAND, 0)
88
89
90 panel_sizer = wx.BoxSizer(wx.VERTICAL)
91 self.panel.SetSizer(panel_sizer)
92
93
94 self.data_box = wx.StaticBox(self.panel, -1)
95 self.set_box_label()
96 self.data_box.SetFont(font.subtitle)
97 sub_sizer = wx.StaticBoxSizer(self.data_box, wx.VERTICAL)
98
99
100 panel_sizer.Add(sub_sizer, self.proportion, wx.ALL|wx.EXPAND, 0)
101
102
103 box_centre = add_border(sub_sizer, border=self.border)
104
105
106 if self.button_placement == 'top':
107 self.add_buttons(box_centre)
108 box_centre.AddSpacer(self.spacing)
109
110
111 self.init_element(box_centre)
112
113
114 self.build_element()
115
116
117 if self.button_placement == 'bottom':
118 box_centre.AddSpacer(self.spacing)
119 self.add_buttons(box_centre)
120
121
122 if self.observer_base_name:
123 self.name = '%s: %s' % (self.observer_base_name, id)
124 else:
125 self.name = id
126
127
128 self.observer_register()
129
130
131 - def Enable(self, enable=True):
132 """Enable or disable the element.
133
134 @keyword enable: The flag specifying if the element should be enabled or disabled.
135 @type enable: bool
136 """
137
138
139 for i in range(len(self.button_info)):
140
141 button = getattr(self, self.button_info[i]['object'])
142
143
144 button.Enable(enable)
145
146
183
184
194
195
197 """Build the spectra listing GUI element in a thread safe wx.CallAfter call."""
198
199
200 self.element.Freeze()
201
202
203 self.set_box_label()
204
205
206 self.element.DeleteAllItems()
207
208
209 self.update_data()
210
211
212 self.size_cols()
213
214
215 event = wx.PyCommandEvent(wx.EVT_SIZE.typeId, self.parent.GetId())
216 wx.PostEvent(self.parent.GetEventHandler(), event)
217
218
219 if not self.proportion:
220
221 n = self.element.GetItemCount()
222
223
224 head = self.height_char + 10
225
226
227 centre = (self.height_char + 6) * n
228
229
230 foot = wx.SystemSettings.GetMetric(wx.SYS_HSCROLL_Y)
231
232
233 height = head + centre + foot
234
235
236 self.element.SetMinSize((-1, height))
237 self.element.Layout()
238
239
240 self.element.Thaw()
241
242
253
254
256 """Create and return the popup menu.
257
258 @keyword id: The ID string for the row that was clicked on.
259 @type id: str
260 @return: The popup menu.
261 @rtype: list of dict of wxID, str, str, method
262 """
263
264
265 return self.popup_menus
266
267
269 """Initialise the GUI element.
270
271 @param sizer: The sizer element to pack the element into.
272 @type sizer: wx.BoxSizer instance
273 """
274
275
276 self.element = wx.ListCtrl(self.panel, -1, style=wx.BORDER_SUNKEN|wx.LC_REPORT)
277
278
279 for i in range(len(self.columns)):
280 self.element.InsertColumn(i, str_to_gui(self.columns[i]))
281
282
283 self.element.SetFont(font.normal)
284
285
286 self.height_char = self.element.GetCharHeight()
287
288
289 self.element.Bind(wx.EVT_SIZE, self.resize)
290 self.element.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.on_right_click)
291 self.element.Bind(wx.EVT_RIGHT_UP, self.on_right_click)
292
293
294 sizer.Add(self.element, self.proportion, wx.ALL|wx.EXPAND, 0)
295
296
298 """Base method which always returns True.
299
300 @return: The answer to the question.
301 @rtype: bool
302 """
303
304
305 return True
306
307
309 """Register and unregister methods with the observer objects.
310
311 @keyword remove: If set to True, then the methods will be unregistered.
312 @type remove: False
313 """
314
315
316 if not remove:
317 status.observers.gui_uf.register(self.name, self.build_element, method_name='build_element')
318 status.observers.pipe_alteration.register(self.name, self.build_element, method_name='build_element')
319
320
321 else:
322 status.observers.gui_uf.unregister(self.name)
323 status.observers.pipe_alteration.unregister(self.name)
324
325
327 """Pop up menu for the right click.
328
329 @param event: The wx event.
330 @type event: wx event
331 """
332
333
334 pos = event.GetPosition()
335
336
337 wx.Yield()
338
339
340 item, flags = self.element.HitTest(pos)
341
342
343 id = None
344 if item != -1:
345 id = self.element.GetItemText(item)
346
347
348 popup_menus = self.generate_popup_menu(id=id)
349
350
351 if popup_menus == []:
352 return
353
354
355 if status.exec_lock.locked():
356 return
357
358
359 menu = wx.Menu()
360
361
362 for i in range(len(popup_menus)):
363
364 info = popup_menus[i]
365
366
367 build_menu_item(menu, id=info['id'], text=info['text'], icon=info['icon'])
368
369
370 self.element.Bind(wx.EVT_MENU, info['method'], id=info['id'])
371
372
373 if status.show_gui:
374 self.element.PopupMenu(menu)
375
376
377 menu.Destroy()
378
379
381 """Catch the resize to allow the element to be resized.
382
383 @param event: The wx event.
384 @type event: wx event
385 """
386
387
388 self.size_cols()
389
390
391 event.Skip()
392
393
395 """Set the label of the StaticBox."""
396
397
398 self.data_box.SetLabel(self.title)
399
400
402 """Set the column sizes."""
403
404
405 x, y = self.element.GetSize()
406
407
408 n = self.element.GetColumnCount()
409
410
411 if n == 0:
412 width = x
413 else:
414 width = int(x / n)
415
416
417 for i in range(n):
418 self.element.SetColumnWidth(i, width)
419