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