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
247
248
250 """Create and return the popup menu.
251
252 @keyword id: The ID string for the row that was clicked on.
253 @type id: str
254 @return: The popup menu.
255 @rtype: list of dict of wxID, str, str, method
256 """
257
258
259 return self.popup_menus
260
261
263 """Initialise the GUI element.
264
265 @param sizer: The sizer element to pack the element into.
266 @type sizer: wx.BoxSizer instance
267 """
268
269
270 self.element = wx.ListCtrl(self.panel, -1, style=wx.BORDER_SUNKEN|wx.LC_REPORT)
271
272
273 for i in range(len(self.columns)):
274 self.element.InsertColumn(i, str_to_gui(self.columns[i]))
275
276
277 self.element.SetFont(font.normal)
278
279
280 self.height_char = self.element.GetCharHeight()
281
282
283 self.element.Bind(wx.EVT_SIZE, self.resize)
284 self.element.Bind(wx.EVT_COMMAND_RIGHT_CLICK, self.on_right_click)
285 self.element.Bind(wx.EVT_RIGHT_UP, self.on_right_click)
286
287
288 sizer.Add(self.element, self.proportion, wx.ALL|wx.EXPAND, 0)
289
290
292 """Base method which always returns True.
293
294 @return: The answer to the question.
295 @rtype: bool
296 """
297
298
299 return True
300
301
303 """Register and unregister methods with the observer objects.
304
305 @keyword remove: If set to True, then the methods will be unregistered.
306 @type remove: False
307 """
308
309
310 if not remove:
311 status.observers.gui_uf.register(self.name, self.build_element, method_name='build_element')
312 status.observers.pipe_alteration.register(self.name, self.build_element, method_name='build_element')
313
314
315 else:
316 status.observers.gui_uf.unregister(self.name)
317 status.observers.pipe_alteration.unregister(self.name)
318
319
321 """Pop up menu for the right click.
322
323 @param event: The wx event.
324 @type event: wx event
325 """
326
327
328 pos = event.GetPosition()
329
330
331 wx.Yield()
332
333
334 item, flags = self.element.HitTest(pos)
335
336
337 id = None
338 if item != -1:
339 id = self.element.GetItemText(item)
340
341
342 popup_menus = self.generate_popup_menu(id=id)
343
344
345 if popup_menus == []:
346 return
347
348
349 if status.exec_lock.locked():
350 return
351
352
353 menu = wx.Menu()
354
355
356 for i in range(len(popup_menus)):
357
358 info = popup_menus[i]
359
360
361 menu.AppendItem(build_menu_item(menu, id=info['id'], text=info['text'], icon=info['icon']))
362
363
364 self.element.Bind(wx.EVT_MENU, info['method'], id=info['id'])
365
366
367 if status.show_gui:
368 self.element.PopupMenu(menu)
369 menu.Destroy()
370
371
373 """Catch the resize to allow the element to be resized.
374
375 @param event: The wx event.
376 @type event: wx event
377 """
378
379
380 self.size_cols()
381
382
383 event.Skip()
384
385
387 """Set the label of the StaticBox."""
388
389
390 self.data_box.SetLabel(self.title)
391
392
394 """Set the column sizes."""
395
396
397 x, y = self.element.GetSize()
398
399
400 n = self.element.GetColumnCount()
401
402
403 if n == 0:
404 width = x
405 else:
406 width = int(x / n)
407
408
409 for i in range(n):
410 self.element.SetColumnWidth(i, width)
411