1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 from button import DisableButton
24 from droplist import Droplist
25 from keymap import get_keyevent_name
26 from label import Label
27 from theme import ui_theme
28 import gobject
29 import gtk
30 from utils import (propagate_expose, cairo_disable_antialias,
31 color_hex_to_cairo, get_widget_root_coordinate,
32 WIDGET_POS_BOTTOM_LEFT, alpha_color_hex_to_cairo)
33
35 '''
36 ComboBox class.
37
38 @undocumented: focus_in_combo
39 @undocumented: focus_out_combo
40 @undocumented: click_drop_button
41 @undocumented: key_press_combo
42 @undocumented: key_release_combo
43 @undocumented: update_select_content
44 @undocumented: set_sensitive
45 @undocumented: expose_combobox_frame
46 '''
47
48 __gsignals__ = {
49 "item-selected" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (str, gobject.TYPE_PYOBJECT, int,)),
50 "key-release" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (str, gobject.TYPE_PYOBJECT, int,)),
51 }
52
53 - def __init__(self,
54 items,
55 droplist_height=None,
56 select_index=0,
57 max_width=None):
58 '''
59 Initialize ComboBox class.
60
61 @param items: ComboBox item, item format: (item_label, item_value)
62 @param droplist_height: You can set maximum height of droplist, default is None.
63 @param select_index: Initialize selected index, default is 0.
64 @param max_width: Maximum width of ComboBox, default is None that width along with content.
65 '''
66
67 gtk.VBox.__init__(self)
68 self.set_can_focus(True)
69 self.items = items
70 self.droplist_height = droplist_height
71 self.select_index = select_index
72 self.focus_flag = False
73
74 self.droplist = Droplist(self.items, max_width=max_width)
75 if self.droplist_height:
76 self.droplist.set_size_request(-1, self.droplist_height)
77 self.width = self.droplist.get_droplist_width()
78 self.height = 22
79 self.label_padding_left = 6
80 self.box = gtk.HBox()
81 self.dropbutton_width = ui_theme.get_pixbuf("combo/dropbutton_normal.png").get_pixbuf().get_width()
82 self.label = Label(self.items[select_index][0],
83 label_width=self.width - self.dropbutton_width - 1 - self.label_padding_left,
84 enable_select=False,
85 enable_double_click=False)
86 self.label.text_color = ui_theme.get_color("menu_font")
87 self.dropbutton = DisableButton(
88 (ui_theme.get_pixbuf("combo/dropbutton_normal.png"),
89 ui_theme.get_pixbuf("combo/dropbutton_hover.png"),
90 ui_theme.get_pixbuf("combo/dropbutton_press.png"),
91 ui_theme.get_pixbuf("combo/dropbutton_disable.png")),
92 )
93
94 self.align = gtk.Alignment()
95 self.align.set(0.5, 0.5, 0.0, 0.0)
96 self.align.set_padding(1, 1, 1 + self.label_padding_left, 1)
97
98 self.pack_start(self.align, False, False)
99 self.align.add(self.box)
100 self.box.pack_start(self.label, False, False)
101 self.box.pack_start(self.dropbutton, False, False)
102
103 self.align.connect("expose-event", self.expose_combobox_frame)
104 self.label.connect("button-press-event", self.click_drop_button)
105 self.dropbutton.connect("button-press-event", self.click_drop_button)
106 self.droplist.connect("item-selected", self.update_select_content)
107 self.droplist.connect("key-release", lambda dl, s, o, i: self.emit("key-release", s, o, i))
108 self.connect("key-press-event", self.key_press_combo)
109 self.connect("key-release-event", self.key_release_combo)
110 self.connect("focus-in-event", self.focus_in_combo)
111 self.connect("focus-out-event", self.focus_out_combo)
112
113 self.keymap = {
114 "Home" : self.select_first_item,
115 "End" : self.select_last_item,
116 "Up" : self.select_prev_item,
117 "Down" : self.select_next_item}
118
120 '''
121 Internal function, focus in ComboBox.
122
123 @param widget: Gtk.Widget instance.
124 @param event: Focus in event.
125 '''
126 self.focus_flag = True
127 self.label.text_color = ui_theme.get_color("menu_select_font")
128
129 self.queue_draw()
130
132 '''
133 Internal function, focus out ComboBox.
134
135 @param widget: Gtk.Widget instance.
136 @param event: Focus out event.
137 '''
138 self.focus_flag = False
139 self.label.text_color = ui_theme.get_color("menu_font")
140
141 self.queue_draw()
142
160
171
182
193
204
206 '''
207 Internal function to handle `key-press-event` signal.
208
209 @param widget: Gtk.Widget instance.
210 @param event: Key press event.
211 '''
212 if not self.droplist.get_visible():
213 key_name = get_keyevent_name(event)
214 if self.keymap.has_key(key_name):
215 self.keymap[key_name]()
216
217 return True
218
220 '''
221 Set select index.
222
223 @param item_index: The index of selected item.
224 '''
225 if 0 <= item_index < len(self.items):
226 item = self.items[item_index]
227 if item:
228 self.select_index = item_index
229 self.label.set_text(item[0])
230
232 '''
233 Get item with given index.
234
235 @return: Return item that match given index, or return None if haven't special index.
236 '''
237 if 0 <= item_index < len(self.items):
238 return self.items[item_index]
239 else:
240 return None
241
243 '''
244 Get current item.
245
246 @return: Return current item.
247 '''
248 return self.get_item_with_index(self.select_index)
249
251 '''
252 Internal function to handle `key-release-event` signal.
253
254 @param widget: Gtk.Widget instance.
255 @param event: Key release event.
256 '''
257 self.emit("key-release",
258 self.items[self.select_index][0],
259 self.items[self.select_index][1],
260 self.select_index)
261
262 - def update_select_content(self, droplist, item_content, item_value, item_index):
263 '''
264 Internal function to update select content.
265
266 @param droplist: Droplist.
267 @param item_content: Item content.
268 @param item_value: Item value.
269 @param item_index: Item index.
270 '''
271 self.select_index = item_index
272 self.label.set_text(item_content)
273
274 self.emit("item-selected", item_content, item_value, item_index)
275
276 self.grab_focus()
277
278 self.queue_draw()
279
281 '''
282 Internal function to overwrite function `set_sensitive`.
283 '''
284 super(ComboBox, self).set_sensitive(sensitive)
285 self.label.set_sensitive(sensitive)
286 self.dropbutton.set_sensitive(sensitive)
287
289 '''
290 Internal function to handle `expose-event` signal of frame.
291 '''
292
293 cr = widget.window.cairo_create()
294 rect = widget.allocation
295
296
297 with cairo_disable_antialias(cr):
298 cr.set_line_width(1)
299 if self.get_sensitive():
300 cr.set_source_rgb(*color_hex_to_cairo(ui_theme.get_color("combo_entry_frame").get_color()))
301 else:
302 cr.set_source_rgb(*color_hex_to_cairo(ui_theme.get_color("disable_frame").get_color()))
303 cr.rectangle(rect.x, rect.y, rect.width, rect.height)
304 cr.stroke()
305
306 if self.focus_flag:
307 cr.set_source_rgba(*alpha_color_hex_to_cairo((ui_theme.get_color("combo_entry_select_background").get_color(), 0.9)))
308 cr.rectangle(rect.x, rect.y, rect.width - 1 - self.dropbutton_width, rect.height - 1)
309 cr.fill()
310
311 cr.set_source_rgba(*alpha_color_hex_to_cairo((ui_theme.get_color("combo_entry_background").get_color(), 0.9)))
312 cr.rectangle(rect.x + rect.width - 1 - self.dropbutton_width, rect.y, self.dropbutton_width, rect.height - 1)
313 cr.fill()
314 else:
315 cr.set_source_rgba(*alpha_color_hex_to_cairo((ui_theme.get_color("combo_entry_background").get_color(), 0.9)))
316 cr.rectangle(rect.x, rect.y, rect.width - 1, rect.height - 1)
317 cr.fill()
318
319
320 propagate_expose(widget, event)
321
322 return True
323
324 gobject.type_register(ComboBox)
325