del net-oscar
[learning-git.git] / pgworksheet_yvesf / pgw / Widgets.py
blobe0d779ea9b2ea2758aa50f084a448319a90fe87f
1 import gtk
2 import math
4 class TrafficLight(gtk.DrawingArea):
5 def __init__(self, start=False):
6 gtk.DrawingArea.__init__(self)
7 self.connect("expose_event", self.expose)
8 self.status = start
10 def expose(self, widget, event):
11 self.context = widget.window.cairo_create()
12 self.draw(self.context)
14 return False
16 def draw(self, context):
17 rect = self.get_allocation()
18 padding = 1
20 context.rectangle(0, 0, rect.width, rect.height)
21 context.stroke()
23 sub = 1
24 #False => Red
25 if self.status == False:
26 context.set_source_rgb(1.0, 0.0, 0.0)
27 context.arc(rect.width / 2, 1 * (rect.height / 4), min([(rect.width/2)-sub, (rect.height/4)-sub]), 0, 2.0 * math.pi)
28 context.fill()
30 context.set_source_rgb(0.0, 0.0, 0.0)
31 context.arc(rect.width / 2, 1 * (rect.height / 4), min([(rect.width/2)-sub, (rect.height/4)-sub]), math.pi, 2*math.pi)
32 context.stroke()
35 #True => Green
36 if self.status == True:
37 context.arc(rect.width / 2, 3 * (rect.height / 4), min([(rect.width/2)-sub, (rect.height/4)-sub]), 0, 2.0 * math.pi)
38 context.set_source_rgb(0.0, 1.0, 0.0)
39 context.fill()
41 context.set_source_rgb(0.0, 0.0, 0.0)
42 context.arc(rect.width / 2, 3 * (rect.height / 4), min([(rect.width/2)-sub, (rect.height/4)-sub]), math.pi, 2*math.pi)
43 context.stroke()
45 def get(self):
46 return self.status
47 def set(self, status):
48 self.status = status
50 self.hide()
51 self.show()
52 def toggle(self):
53 self.set(not self.get())
59 #=======================================================================================================0
60 #=======================================================================================================0
61 #=======================================================================================================0
62 #=======================================================================================================0
63 #=======================================================================================================0
64 """Autocomplete feature for gtk.TextView
65 This code is inspired and adapted from the Advene Project who has been inspired by the Scribes project
66 (http://scribes.sf.net/) - GPLv2
67 """
70 import pygtk, gtk
71 import pgw, pgw.Undo, pgw.Syntax
72 import gettext; _ = gettext.gettext
73 class SQLTextView(gtk.VBox):
74 def __init__(self, db):
75 gtk.VBox.__init__(self)
77 self.enable_completion = True
79 undo = pgw.Undo.Undo()
80 scroll = gtk.ScrolledWindow()
81 scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
82 scroll.set_property("height-request", 150)
83 scroll.set_shadow_type(gtk.SHADOW_NONE)
84 self.buffer = gtk.TextBuffer()
85 self.buffer.connect('delete-range', undo.text_deleted)
86 self.buffer.connect('insert-text', undo.text_inserted)
88 syntax = pgw.Syntax.Syntax(self.buffer)
89 buffer_handlers = []
90 buffer_handlers.append(self.buffer.connect('delete-range',
91 syntax.text_deleted))
92 buffer_handlers.append(self.buffer.connect('insert-text',
93 syntax.text_inserted))
94 buffer_handlers.append(self.buffer.connect('changed',
95 syntax.text_changed))
96 self.textview = gtk.TextView(self.buffer)
97 scroll.add(self.textview)
99 self.add(scroll)
101 self.is_visible=False
102 self.word_list=None
104 #Completion
105 self.widget=self.build_widget()
106 self.last = ""
109 self.connect()
111 def connect(self):
112 """Register the various callbacks for completion.
114 self.textview.connect("key-press-event", self.key_press_event_cb)
115 self.textview.connect("focus-out-event", self.hide_completion_window)
116 self.textview.get_buffer().connect("delete-range", self.hide_completion_window)
117 self.textview.get_buffer().connect_after("insert-text", self.insert_text_cb)
118 self.textview.connect("paste-clipboard", self.hide_completion_window)
119 self.textview.connect_after("paste-clipboard", self.hide_completion_window)
120 #self.textview.connect("button-press-event", self.__button_press_event_cb)
121 return True
123 def insert_text_cb(self, textbuffer, iterator, text, length):
124 """Handles callback when the "insert-text" signal is emitted.
126 if length > 1:
127 self.hide_completion_window()
128 else:
129 self.check_completion()
130 return False
132 def hide_completion_window(self, *p):
133 self.widget.hide_all()
134 self.is_visible=False
136 def show_completion_window(self, *p):
137 width, height = self.widget.size_request()
138 if width <= 200:
139 width=200
140 else:
141 width += 28
142 if height <= 200:
143 height=200
144 else:
145 height += 28
146 self.widget.resize(width, height)
147 self.widget.set_property("width-request", width)
148 self.widget.set_property("height-request", height)
149 self.position_window(width, height)
150 self.widget.show_all()
151 self.position_window(width, height)
152 self.is_visible=True
154 def get_cursor_rectangle(self):
155 b=self.textview.get_buffer()
156 cursor_iterator=b.get_iter_at_mark(b.get_insert())
157 rectangle = self.textview.get_iter_location(cursor_iterator)
158 return rectangle
160 def get_cursor_textview_coordinates(self):
161 rectangle=self.get_cursor_rectangle()
162 # Get the cursor's window coordinates.
163 position = self.textview.buffer_to_window_coords(gtk.TEXT_WINDOW_TEXT, rectangle.x, rectangle.y)
164 cursor_x = position[0]
165 cursor_y = position[1]
166 return cursor_x, cursor_y
168 def get_cursor_size(self):
169 """Get the cursor's size.
171 rectangle=self.get_cursor_rectangle()
172 return rectangle.width, rectangle.height
174 def position_window(self, width, height):
175 """Position the completion window in the text editor's buffer.
177 @param width: The completion window's width.
178 @type width: An Integer object.
180 @param height: The completion window's height.
181 @type height: An Integer object.
183 # Get the cursor's coordinate and size.
184 cursor_x, cursor_y = self.get_cursor_textview_coordinates()
185 cursor_height = self.get_cursor_size()[1]
186 # Get the text editor's textview coordinate and size.
187 window = self.textview.get_window(gtk.TEXT_WINDOW_TEXT)
188 rectangle = self.textview.get_visible_rect()
189 window_x, window_y = window.get_origin()
190 window_width, window_height = rectangle.width, rectangle.height
192 # Determine where to position the completion window.
193 position_x = window_x + cursor_x
194 position_y = window_y + cursor_y + cursor_height
196 # If the completion window extends past the text editor's buffer,
197 # reposition the completion window inside the text editor's buffer area.
198 if position_x + width > window_x + window_width:
199 position_x = (window_x + window_width) - width
200 if position_y + height > window_y + window_height:
201 position_y = (window_y + cursor_y) - height
202 #if not_(self.__signals_are_blocked):
203 x, y = self.widget.get_position()
205 if position_y != y:
206 position_x = x
208 if position_x != x or position_y != y:
209 # Set the window's new position.
210 self.widget.move(position_x, position_y)
212 def populate_model(self, completion_list):
213 """Populate the view's data model.
215 @param self: Reference to the CompletionTreeView instance.
216 @type self: A CompletionTreeView object.
218 if completion_list != self.word_list:
219 self.word_list = completion_list
220 self.model.clear()
221 for word in self.word_list:
222 self.model.append([word])
223 self.treeview.columns_autosize()
224 self.treeview.get_selection().select_path(0)
226 def get_word_before_cursor(self):
227 b=self.textview.get_buffer()
228 cursor_position=b.get_iter_at_mark(b.get_insert())
229 word_start=cursor_position.copy()
230 word_start.backward_word_start()
231 return word_start.get_text(cursor_position)
233 def insert_word_completion(self, path):
234 """Insert item selected in the completion window into the text editor's
235 buffer.
237 @param path: The selected row in the completion window.
238 @type path: A gtk.TreeRow object.
240 # Get the selected completion string.
241 completion_string = self.model[path[0]][0].decode("utf8")
243 word=self.get_word_before_cursor().encode('utf8')
244 complete=completion_string.replace(word, '')
245 b=self.textview.get_buffer()
246 b.begin_user_action()
247 b.insert_at_cursor(complete)
248 b.end_user_action()
249 return
251 """ Returns a sorted list of Completions"""
252 def get_completions(self, word, context):
253 print "SQLTextView: get_completions(word=%s, context=%s)"%(word, context)
255 b=self.textview.get_buffer()
256 cursor_pos = b.get_iter_at_mark(b.get_insert())
257 w_start = cursor_pos.copy()
258 w_start.backward_word_start()
259 word = w_start.get_text( cursor_pos)
260 if word != "" and word.strip() in pgw.Syntax.KEYWORDS:
261 self.last = word.strip()
262 return pgw.Syntax.KEYWORDS[word.strip()]
263 elif word != "" and self.last in pgw.Syntax.KEYWORDS:
264 ret = []
265 for it in pgw.Syntax.KEYWORDS[self.last]:
266 if type(it) == str and it.startswith(word):
267 ret.append(it)
268 return ret
269 ret = []
270 for it in pgw.Syntax.KEYWORDS.keys():
271 if type(it) == str and it.startswith(word):
272 ret.append(it)
273 return ret
276 def check_completion(self):
277 word = self.get_word_before_cursor()
278 if self.enable_completion and word:
279 if len(word) < 1:
280 return False
281 matches=self.get_completions(word, context=self.buffer)
282 if matches:
283 self.populate_model(matches)
284 self.show_completion_window()
285 else:
286 # Hide the window
287 self.hide_completion_window()
288 else:
289 self.hide_completion_window()
290 return False
292 def key_press_event_cb(self, widget, event):
293 """Handles "key-press-event" for the treeview and textview.
295 This function allows the "Up" and "Down" arrow keys to work in
296 the word completion window.
298 if not self.is_visible:
299 return False
301 if event.keyval in (gtk.keysyms.Tab, gtk.keysyms.Right, gtk.keysyms.Left,
302 gtk.keysyms.Home, gtk.keysyms.End, gtk.keysyms.Insert,
303 gtk.keysyms.Delete,
304 gtk.keysyms.Page_Up, gtk.keysyms.Page_Down,
305 gtk.keysyms.Escape):
306 self.hide_completion_window()
307 return True
309 # Get the selected item on the completion window.
310 selection = self.treeview.get_selection()
311 # Get the model and iterator of the selected item.
312 model, iterator = selection.get_selected()
313 # If for whatever reason the selection is lost, select the first row
314 # automatically when the up or down arrow key is pressed.
315 if not iterator:
316 selection.select_path((0,))
317 model, iterator = selection.get_selected()
318 path = model.get_path(iterator)
319 if event.keyval == gtk.keysyms.Return:
320 # Insert the selected item into the editor's buffer when the enter key
321 # event is detected.
322 self.treeview.row_activated(path, self.treeview.get_column(0))
323 elif event.keyval == gtk.keysyms.Up:
324 # If the up key is pressed check to see if the first row is selected.
325 # If it is, select the last row. Otherwise, get the path to the row
326 # above and select it.
327 if not path[0]:
328 number_of_rows = len(model)
329 selection.select_path(number_of_rows - 1)
330 self.treeview.scroll_to_cell(number_of_rows - 1)
331 else:
332 selection.select_path((path[0] - 1, ))
333 self.treeview.scroll_to_cell((path[0] - 1, ))
334 elif event.keyval == gtk.keysyms.Down:
335 # Get the iterator of the next row.
336 next_iterator = model.iter_next(iterator)
337 # If the next row exists, select it, if not select the first row.
338 if next_iterator:
339 selection.select_iter(next_iterator)
340 path = model.get_path(next_iterator)
341 self.treeview.scroll_to_cell(path)
342 else:
343 selection.select_path(0)
344 self.treeview.scroll_to_cell(0)
345 else:
346 return False
347 return True
349 def build_widget(self):
350 w=gtk.Window(gtk.WINDOW_POPUP)
352 w.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_MENU)
353 w.set_size_request(200, 200)
355 self.treeview=gtk.TreeView()
357 self.model = gtk.ListStore(str)
358 renderer = gtk.CellRendererText()
359 col=gtk.TreeViewColumn("", renderer, text=0)
360 col.set_expand(False)
362 self.treeview.append_column(col)
363 self.treeview.set_headers_visible(False)
364 self.treeview.set_rules_hint(True)
365 self.treeview.set_hover_selection(True)
366 self.treeview.set_model(self.model)
368 def treeview_row_activated_cb(treeview, path, column):
369 """Handles "row-activated" in the treeview.
371 self.insert_word_completion(path)
372 self.hide_completion_window()
373 return True
374 self.treeview.connect("row-activated", treeview_row_activated_cb)
376 style = self.textview.get_style()
377 color = style.base[gtk.STATE_SELECTED]
378 self.treeview.modify_base(gtk.STATE_ACTIVE, color)
380 scroll=gtk.ScrolledWindow()
381 scroll.add(self.treeview)
382 scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
383 scroll.set_border_width(2)
384 w.add(scroll)
386 return w