5 # Copyright (c) 2007-2008 Huang Peng <shawn.p.huang@gmail.com>
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2 of the License, or (at your option) any later version.
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this program; if not, write to the
19 # Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20 # Boston, MA 02111-1307 USA
27 from ibus
.gtk
import PangoAttrList
29 class HSeparator (gtk
.HBox
):
31 gtk
.HBox
.__init
__ (self
)
32 self
.pack_start (gtk
.HSeparator (), True, True, 4)
34 class VSeparator (gtk
.VBox
):
36 gtk
.VBox
.__init
__ (self
)
37 self
.pack_start (gtk
.VSeparator (), True, True, 4)
39 class CandidateArea (gtk
.HBox
):
40 def __init__ (self
, orientation
):
41 gtk
.HBox
.__init
__ (self
)
42 self
._orientation
= orientation
46 def _create_ui (self
):
47 if self
._orientation
== gtk
.ORIENTATION_VERTICAL
:
48 self
._vbox
1 = gtk
.VBox ()
49 self
._vbox
2 = gtk
.VBox ()
50 self
.pack_start (self
._vbox
1, False, False, 4)
51 self
.pack_start (VSeparator(), False, False, 0)
52 self
.pack_start (self
._vbox
2, True, True, 4)
54 for i
in xrange (1, 10):
55 label1
= gtk
.Label ("%d." % i
)
56 label1
.set_alignment (0.0, 0.5)
57 label1
.set_no_show_all (True)
60 label2
.set_alignment (0.0, 0.5)
61 label2
.set_no_show_all (True)
63 if self
._orientation
== gtk
.ORIENTATION_VERTICAL
:
64 label1
.set_property ("xpad", 8)
65 label2
.set_property ("xpad", 8)
66 self
._vbox
1.pack_start (label1
, False, False, 2)
67 self
._vbox
2.pack_start (label2
, False, False, 2)
70 hbox
.pack_start (label1
, False, False, 1)
71 hbox
.pack_start (label2
, False, False, 1)
72 self
.pack_start (hbox
, False, False, 4)
74 self
._labels
.append ((label1
, label2
))
76 self
._labels
[0][0].show ()
77 self
._labels
[0][1].show ()
79 def set_candidates (self
, candidates
, focus_candidate
= 0):
80 assert len (candidates
) <= len (self
._labels
)
82 for text
, attrs
in candidates
:
83 self
._labels
[i
][1].set_text (text
)
84 self
._labels
[i
][1].set_attributes (attrs
)
85 self
._labels
[i
][0].show ()
86 self
._labels
[i
][1].show ()
87 if i
== focus_candidate
:
88 self
._labels
[i
][0].set_state (gtk
.STATE_SELECTED
)
89 self
._labels
[i
][1].set_state (gtk
.STATE_SELECTED
)
91 self
._labels
[i
][0].set_state (gtk
.STATE_NORMAL
)
92 self
._labels
[i
][1].set_state (gtk
.STATE_NORMAL
)
96 for label1
, label2
in self
._labels
[max (1, len(candidates
)):]:
100 if len (candidates
) == 0:
101 self
._labels
[0][0].set_text ("")
102 self
._labels
[0][1].set_text ("")
104 self
._labels
[0][0].set_text ("1.")
106 class CandidatePanel (gtk
.VBox
):
108 'orientation' : (gtk
.Orientation
, # type
109 'orientation of candidates', # nick name
110 'the orientation of candidates list', # description
112 gobject
.PARAM_READWRITE
) # flags
117 gobject
.SIGNAL_RUN_FIRST
,
121 gobject
.SIGNAL_RUN_FIRST
,
127 gtk
.VBox
.__init
__ (self
)
128 self
._tooltips
= gtk
.Tooltips ()
130 self
._toplevel
= gtk
.Window (gtk
.WINDOW_POPUP
)
131 self
._toplevel
.add (self
)
132 self
._toplevel
.add_events (
133 gdk
.BUTTON_PRESS_MASK | \
134 gdk
.BUTTON_RELEASE_MASK | \
135 gdk
.BUTTON1_MOTION_MASK
)
136 self
._begin
_move
= False
137 self
._toplevel
.connect ("button-press-event", self
._button
_press
_event
_cb
)
138 self
._toplevel
.connect ("button-release-event", self
._button
_release
_event
_cb
)
139 self
._toplevel
.connect ("motion-notify-event", self
._motion
_notify
_event
_cb
)
141 self
._orientation
= gtk
.ORIENTATION_HORIZONTAL
142 self
._orientation
= gtk
.ORIENTATION_VERTICAL
143 self
._show
_preedit
_string
= False
144 self
._show
_aux
_string
= False
145 self
._show
_lookup
_table
= False
146 self
._preedit
_string
= ""
147 self
._preedit
_attrs
= pango
.AttrList ()
148 self
._aux
_string
= ""
149 self
._aux
_attrs
= pango
.AttrList ()
150 self
._lookup
_table
= None
154 def _recreate_ui (self
):
158 # create preedit label
159 self
._preedit
_label
= gtk
.Label (self
._preedit
_string
)
160 self
._preedit
_label
.set_attributes (self
._preedit
_attrs
)
161 self
._preedit
_label
.set_alignment (0.0, 0.5)
162 self
._preedit
_label
.set_padding (8, 0)
163 self
._preedit
_label
.set_no_show_all (True)
164 if self
._show
_preedit
_string
:
165 self
._preedit
_label
.show ()
168 self
._aux
_label
= gtk
.Label (self
._aux
_string
)
169 self
._aux
_label
.set_attributes (self
._aux
_attrs
)
170 self
._aux
_label
.set_alignment (0.0, 0.5)
171 self
._aux
_label
.set_padding (8, 0)
172 self
._tooltips
.set_tip (self
._aux
_label
, "Aux string")
173 self
._aux
_label
.set_no_show_all (True)
174 if self
._show
_aux
_string
:
175 self
._aux
_label
.show ()
177 # create candidates area
178 self
._candidate
_area
= CandidateArea (self
._orientation
)
179 self
._candidate
_area
.set_no_show_all (True)
180 self
.update_lookup_table (self
._lookup
_table
, self
._show
_lookup
_table
)
183 self
._state
_label
= gtk
.Label ()
184 self
._state
_label
.set_size_request (20, -1)
187 self
._prev
_button
= gtk
.Button ()
188 self
._prev
_button
.connect ("clicked", lambda x
: self
.emit ("cursor-up"))
189 self
._prev
_button
.set_relief (gtk
.RELIEF_NONE
)
190 self
._tooltips
.set_tip (self
._prev
_button
, "Previous candidate")
192 self
._next
_button
= gtk
.Button ()
193 self
._next
_button
.connect ("clicked", lambda x
: self
.emit ("cursor-down"))
194 self
._next
_button
.set_relief (gtk
.RELIEF_NONE
)
195 self
._tooltips
.set_tip (self
._next
_button
, "Next candidate")
197 self
._pack
_all
_widgets
()
199 def _pack_all_widgets (self
):
200 if self
._orientation
== gtk
.ORIENTATION_VERTICAL
:
201 # package all widgets in vertical mode
203 image
.set_from_stock (gtk
.STOCK_GO_UP
, gtk
.ICON_SIZE_MENU
)
204 self
._prev
_button
.set_image (image
)
207 image
.set_from_stock (gtk
.STOCK_GO_DOWN
, gtk
.ICON_SIZE_MENU
)
208 self
._next
_button
.set_image (image
)
210 vbox
.pack_start (self
._preedit
_label
, False, False, 0)
211 vbox
.pack_start (self
._aux
_label
, False, False, 0)
212 self
.pack_start (vbox
, False, False, 5)
213 self
.pack_start (HSeparator (), False, False)
214 self
.pack_start (self
._candidate
_area
, False, False, 2)
215 self
.pack_start (HSeparator (), False, False)
217 hbox
.pack_start (self
._state
_label
, True, True)
218 hbox
.pack_start (VSeparator (), False, False)
219 hbox
.pack_start (self
._prev
_button
, False, False, 2)
220 hbox
.pack_start (self
._next
_button
, False, False, 2)
221 self
.pack_start (hbox
, False, False)
223 # package all widgets in HORIZONTAL mode
225 image
.set_from_stock (gtk
.STOCK_GO_BACK
, gtk
.ICON_SIZE_MENU
)
226 self
._prev
_button
.set_image (image
)
229 image
.set_from_stock (gtk
.STOCK_GO_FORWARD
, gtk
.ICON_SIZE_MENU
)
230 self
._next
_button
.set_image (image
)
233 vbox
.pack_start (self
._preedit
_label
, False, False, 0)
234 vbox
.pack_start (self
._aux
_label
, False, False, 0)
235 self
.pack_start (vbox
, False, False, 5)
236 self
.pack_start (HSeparator (), False, False)
238 hbox
.pack_start (self
._candidate
_area
, True, True, 2)
239 hbox
.pack_start (VSeparator (), False, False)
240 hbox
.pack_start (self
._prev
_button
, False, False, 2)
241 hbox
.pack_start (self
._next
_button
, False, False, 2)
242 self
.pack_start (hbox
, False, False)
247 def show_preedit_string (self
):
248 self
._show
_preedit
_string
= True
249 self
._preedit
_label
.show ()
250 self
._check
_show
_states
()
252 def hide_preedit_string (self
):
253 self
._show
_preedit
_string
= False
254 self
._preedit
_label
.hide ()
255 self
._check
_show
_states
()
257 def update_preedit (self
, text
, attrs
, cursor_pos
, show
):
258 attrs
= PangoAttrList (attrs
, text
)
260 self
.show_preedit_string ()
262 self
.hide_preedit_string ()
263 self
._preedit
_string
= text
264 self
._preedit
_label
.set_text (text
)
266 attrs
= pango
.AttrList ()
267 self
._preedit
_attrs
= attrs
268 self
._preedit
_label
.set_attributes (attrs
)
270 def show_aux_string (self
):
271 self
._show
_aux
_string
= True
272 self
._aux
_label
.show ()
273 self
._check
_show
_states
()
275 def hide_aux_string (self
):
276 self
._show
_aux
_string
= False
277 self
._aux
_label
.hide ()
278 self
._check
_show
_states
()
280 def update_aux_string (self
, text
, attrs
, show
):
281 attrs
= PangoAttrList (attrs
, text
)
284 self
.show_aux_string ()
286 self
.hide_aux_string ()
288 self
._aux
_string
= text
289 self
._aux
_label
.set_text (text
)
291 attrs
= pango
.AttrList ()
292 self
._aux
_attrs
= attrs
293 self
._aux
_label
.set_attributes (attrs
)
295 def show_lookup_table (self
):
296 self
._show
_lookup
_table
= True
297 self
._candidate
_area
.set_no_show_all (False)
298 self
._candidate
_area
.show_all ()
299 self
._check
_show
_states
()
301 def hide_lookup_table (self
):
302 self
._show
_lookup
_table
= False
303 self
._candidate
_area
.hide_all ()
304 self
._candidate
_area
.set_no_show_all (True)
305 self
._check
_show
_states
()
307 def update_lookup_table (self
, lookup_table
, show
):
308 if lookup_table
== None:
309 lookup_table
= ibus
.LookupTable ()
312 self
.show_lookup_table ()
314 self
.hide_lookup_table ()
316 self
._lookup
_table
= lookup_table
317 candidates
= self
._lookup
_table
.get_canidates_in_current_page ()
318 candidates
= map (lambda x
: (x
[0], PangoAttrList (x
[1], x
[0])), candidates
)
319 self
._candidate
_area
.set_candidates (candidates
, self
._lookup
_table
.get_cursor_pos_in_current_page ())
321 def _check_show_states (self
):
322 if self
._show
_preedit
_string
or \
323 self
._show
_aux
_string
or \
324 self
._show
_lookup
_table
:
333 self
.hide_preedit_string ()
334 self
.hide_aux_string ()
335 self
.hide_lookup_table ()
336 self
.update_preedit ("", None, 0, False)
337 self
.update_aux_string ("", None, False)
338 self
.update_lookup_table (None, False)
340 def set_orientation (self
, orientation
):
341 if self
._orientation
== orientation
:
343 self
._orientation
= orientation
345 if self
._toplevel
.flags () & gtk
.VISIBLE
:
348 def get_orientation (self
):
349 return self
._orientation
351 def do_set_property (self
, property, value
):
352 if property == 'orientation':
353 self
.set_orientation (value
)
355 return gtk
.DrawingArea
.do_set_property (property, value
)
357 def do_get_property (self
, property):
358 if property == 'orientation':
359 return self
._orientation
361 return gtk
.DrawingArea
.do_get_property (property)
363 def do_expose_event (self
, event
):
364 self
.style
.paint_box (self
.window
,
370 self
.allocation
.x
, self
.allocation
.y
,
371 self
.allocation
.width
, self
.allocation
.height
)
373 gtk
.VBox
.do_expose_event (self
, event
)
375 def do_size_request (self
, requisition
):
376 gtk
.VBox
.do_size_request (self
, requisition
)
377 self
._toplevel
.resize (1, 1)
379 def _button_press_event_cb (self
, widget
, event
):
380 if event
.button
== 1:
381 self
._begin
_move
= True
382 self
._press
_pos
= event
.x_root
, event
.y_root
383 self
._toplevel
.window
.set_cursor (gdk
.Cursor (gdk
.FLEUR
))
386 if event
.button
== 3:
387 if self
.get_orientation () == gtk
.ORIENTATION_HORIZONTAL
:
388 self
.set_orientation (gtk
.ORIENTATION_VERTICAL
)
391 self
.set_orientation (gtk
.ORIENTATION_HORIZONTAL
)
395 def _button_release_event_cb (self
, widget
, event
):
396 if event
.button
== 1:
398 self
._begin
_move
= False
399 self
._toplevel
.window
.set_cursor (gdk
.Cursor (gdk
.LEFT_PTR
))
403 def _motion_notify_event_cb (self
, widget
, event
):
404 if self
._begin
_move
!= True:
406 x
, y
= self
._toplevel
.get_position ()
407 x
= int (x
+ event
.x_root
- self
._press
_pos
[0])
408 y
= int (y
+ event
.y_root
- self
._press
_pos
[1])
409 self
._toplevel
.move (x
, y
)
410 self
._press
_pos
= event
.x_root
, event
.y_root
414 gtk
.VBox
.show_all (self
)
415 self
._toplevel
.show_all ()
418 gtk
.VBox
.hide_all (self
)
419 self
._toplevel
.hide_all ()
421 def move (self
, x
, y
):
422 self
._toplevel
.move (x
, y
)
424 gobject
.type_register (CandidatePanel
, "IBusCandidate")