vimamsa 0.1.5 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,560 @@
1
+ $idle_scroll_to_mark = false
2
+
3
+ def gui_open_file_dialog(dirpath)
4
+ dialog = Gtk::FileChooserDialog.new(:title => "Open file",
5
+ :action => :open,
6
+ :buttons => [[Gtk::Stock::OPEN, :accept],
7
+ [Gtk::Stock::CANCEL, :cancel]])
8
+ dialog.set_current_folder(dirpath)
9
+
10
+ dialog.signal_connect("response") do |dialog, response_id|
11
+ if response_id == Gtk::ResponseType::ACCEPT
12
+ open_new_file(dialog.filename)
13
+ # debug "uri = #{dialog.uri}"
14
+ end
15
+ dialog.destroy
16
+ end
17
+ dialog.run
18
+ end
19
+
20
+ def gui_file_saveas(dirpath)
21
+ dialog = Gtk::FileChooserDialog.new(:title => "Save as",
22
+ :action => :save,
23
+ :buttons => [[Gtk::Stock::SAVE, :accept],
24
+ [Gtk::Stock::CANCEL, :cancel]])
25
+ dialog.set_current_folder(dirpath)
26
+ dialog.signal_connect("response") do |dialog, response_id|
27
+ if response_id == Gtk::ResponseType::ACCEPT
28
+ file_saveas(dialog.filename)
29
+ end
30
+ dialog.destroy
31
+ end
32
+
33
+ dialog.run
34
+ end
35
+
36
+ def idle_func
37
+ # debug "IDLEFUNC"
38
+ if $idle_scroll_to_mark
39
+ # Ripl.start :binding => binding
40
+ # $view.get_visible_rect
41
+ vr = $view.visible_rect
42
+
43
+ # iter = b.get_iter_at(:offset => i)
44
+
45
+ b = $view.buffer
46
+ iter = b.get_iter_at(:offset => b.cursor_position)
47
+ iterxy = $view.get_iter_location(iter)
48
+ # debug "ITERXY" + iterxy.inspect
49
+ # Ripl.start :binding => binding
50
+
51
+ intr = iterxy.intersect(vr)
52
+ if intr.nil?
53
+ $view.set_cursor_pos($view.buffer.cursor_position)
54
+ else
55
+ $idle_scroll_to_mark = false
56
+ end
57
+
58
+ sleep(0.1)
59
+ end
60
+ sleep(0.01)
61
+ return true
62
+ end
63
+
64
+ def center_on_current_line()
65
+ b = $view.buffer
66
+ iter = b.get_iter_at(:offset => b.cursor_position)
67
+ within_margin = 0.0 #margin as a [0.0,0.5) fraction of screen size
68
+ use_align = true
69
+ xalign = 0.0 #0.0=top 1.0=bottom, 0.5=center
70
+ yalign = 0.5
71
+ $view.scroll_to_iter(iter, within_margin, use_align, xalign, yalign)
72
+ end
73
+
74
+ def get_visible_area()
75
+ view = $view
76
+ vr = view.visible_rect
77
+ startpos = view.get_iter_at_position_raw(vr.x, vr.y)[1].offset
78
+ endpos = view.get_iter_at_position_raw(vr.x + vr.width, vr.y + vr.height)[1].offset
79
+ return [startpos, endpos]
80
+ end
81
+
82
+ def page_up
83
+ $view.signal_emit("move-cursor", Gtk::MovementStep.new(:PAGES), -1, false)
84
+ return true
85
+ end
86
+
87
+ def page_down
88
+ $view.signal_emit("move-cursor", Gtk::MovementStep.new(:PAGES), 1, false)
89
+ return true
90
+ end
91
+
92
+ def paste_system_clipboard()
93
+ # clipboard = $vmag.window.get_clipboard(Gdk::Selection::CLIPBOARD)
94
+ utf8_string = Gdk::Atom.intern("UTF8_STRING")
95
+ # x = clipboard.request_contents(utf8_string)
96
+
97
+ widget = Gtk::Invisible.new
98
+ clipboard = Gtk::Clipboard.get_default($vmag.window.display)
99
+ received_text = ""
100
+
101
+ target_string = Gdk::Selection::TARGET_STRING
102
+ ti = clipboard.request_contents(target_string)
103
+
104
+ # clipboard.request_contents(target_string) do |_clipboard, selection_data|
105
+ # received_text = selection_data.text
106
+ # debug "received_text=#{received_text}"
107
+ # end
108
+ if clipboard.wait_is_text_available?
109
+ received_text = clipboard.wait_for_text
110
+ end
111
+
112
+ if received_text != "" and !received_text.nil?
113
+ max_clipboard_items = 100
114
+ if received_text != $clipboard[-1]
115
+ #TODO: HACK
116
+ $paste_lines = false
117
+ end
118
+ $clipboard << received_text
119
+ # debug $clipboard[-1]
120
+ $clipboard = $clipboard[-([$clipboard.size, max_clipboard_items].min)..-1]
121
+ end
122
+ return received_text
123
+ end
124
+
125
+ def set_system_clipboard(arg)
126
+ # return if arg.class != String
127
+ # return if s.size < 1
128
+ # utf8_string = Gdk::Atom.intern("UTF8_STRING")
129
+ widget = Gtk::Invisible.new
130
+ clipboard = Gtk::Clipboard.get_default($vmag.window.display)
131
+ clipboard.text = arg
132
+ end
133
+
134
+ def gui_create_buffer(id)
135
+ debug "gui_create_buffer(#{id})"
136
+ buf1 = GtkSource::Buffer.new()
137
+ view = VSourceView.new()
138
+
139
+ view.set_highlight_current_line(true)
140
+ view.set_show_line_numbers(true)
141
+ view.set_buffer(buf1)
142
+
143
+ ssm = GtkSource::StyleSchemeManager.new
144
+ ssm.set_search_path(ssm.search_path << ppath("styles/"))
145
+ # sty = ssm.get_scheme("dark")
146
+ sty = ssm.get_scheme("molokai_edit")
147
+ # debug ssm.scheme_ids
148
+
149
+ view.buffer.highlight_matching_brackets = true
150
+ view.buffer.style_scheme = sty
151
+
152
+ provider = Gtk::CssProvider.new
153
+ provider.load(data: "textview { font-family: Monospace; font-size: 11pt; }")
154
+ # provider.load(data: "textview { font-family: Arial; font-size: 12pt; }")
155
+ view.style_context.add_provider(provider)
156
+ view.wrap_mode = :char
157
+ view.set_tab_width(conf(:tab_width))
158
+
159
+
160
+ $vmag.buffers[id] = view
161
+ end
162
+
163
+ def gui_set_file_lang(id, lname)
164
+ view = $vmag.buffers[id]
165
+ lm = GtkSource::LanguageManager.new
166
+ lang = nil
167
+ lm.set_search_path(lm.search_path << ppath("lang/"))
168
+ lang = lm.get_language(lname)
169
+
170
+ view.buffer.language = lang
171
+ view.buffer.highlight_syntax = true
172
+ end
173
+
174
+ def gui_add_image(imgpath, pos)
175
+ end
176
+
177
+ # TODO:?
178
+ def gui_select_window_close(arg = nil)
179
+ end
180
+
181
+ # def set_window_title(str)
182
+ # unimplemented
183
+ # end
184
+
185
+ def gui_set_buffer_contents(id, txt)
186
+ # $vbuf.set_text(txt)
187
+ debug "gui_set_buffer_contents(#{id}, txt)"
188
+
189
+ $vmag.buffers[id].buffer.set_text(txt)
190
+ end
191
+
192
+ def gui_set_cursor_pos(id, pos)
193
+ $view.set_cursor_pos(pos)
194
+ # Ripl.start :binding => binding
195
+ end
196
+
197
+ def gui_set_current_buffer(id)
198
+ view = $vmag.buffers[id]
199
+ debug "gui_set_current_buffer(#{id}), view=#{view}"
200
+ buf1 = view.buffer
201
+ $vmag.view = view
202
+ $vmag.buf1 = buf1
203
+ $view = view
204
+ $vbuf = buf1
205
+
206
+ $vmag.sw.remove($vmag.sw.child) if !$vmag.sw.child.nil?
207
+ $vmag.sw.add(view)
208
+
209
+ view.grab_focus
210
+ #view.set_focus(10)
211
+ view.set_cursor_visible(true)
212
+ #view.move_cursor(1, 1, false)
213
+ view.place_cursor_onscreen
214
+
215
+ #TODO:
216
+ # itr = view.buffer.get_iter_at(:offset => 0)
217
+ # view.buffer.place_cursor(itr)
218
+
219
+ # wtitle = ""
220
+ # wtitle = buf.fname if !buf.fname.nil?
221
+ $vmag.sw.show_all
222
+ end
223
+
224
+ def gui_set_window_title(wtitle, subtitle = "")
225
+ $vmag.window.title = wtitle
226
+ $vmag.window.titlebar.subtitle = subtitle
227
+ end
228
+
229
+ class VMAgui
230
+ attr_accessor :buffers, :sw, :view, :buf1, :window
231
+
232
+ VERSION = "1.0"
233
+
234
+ HEART = "♥"
235
+ RADIUS = 150
236
+ N_WORDS = 5
237
+ FONT = "Serif 18"
238
+ TEXT = "I ♥ GTK+"
239
+
240
+ def initialize()
241
+ @show_overlay = true
242
+ @da = nil
243
+ @buffers = {}
244
+ @view = nil
245
+ @buf1 = nil
246
+ end
247
+
248
+ def run
249
+ init_window
250
+ # init_rtext
251
+ Gtk.main
252
+ end
253
+
254
+ def start_overlay_draw()
255
+ @da = Gtk::Fixed.new
256
+ @overlay.add_overlay(@da)
257
+ @overlay.set_overlay_pass_through(@da, true)
258
+ end
259
+
260
+ def clear_overlay()
261
+ if @da != nil
262
+ @overlay.remove(@da)
263
+ end
264
+ end
265
+
266
+ def overlay_draw_text(text, textpos)
267
+ # debug "overlay_draw_text #{[x,y]}"
268
+ (x, y) = @view.pos_to_coord(textpos)
269
+ # debug "overlay_draw_text #{[x,y]}"
270
+ label = Gtk::Label.new("<span background='#00000088' foreground='#ff0000' weight='ultrabold'>#{text}</span>")
271
+ label.use_markup = true
272
+ @da.put(label, x, y)
273
+ end
274
+
275
+ def end_overlay_draw()
276
+ @da.show_all
277
+ end
278
+
279
+ def toggle_overlay
280
+ @show_overlay = @show_overlay ^ 1
281
+ if !@show_overlay
282
+ if @da != nil
283
+ @overlay.remove(@da)
284
+ end
285
+ return
286
+ else
287
+ @da = Gtk::Fixed.new
288
+ @overlay.add_overlay(@da)
289
+ @overlay.set_overlay_pass_through(@da, true)
290
+ end
291
+
292
+ (startpos, endpos) = get_visible_area
293
+ s = @view.buffer.text
294
+ wpos = s.enum_for(:scan, /\W(\w)/).map { Regexp.last_match.begin(0) + 1 }
295
+ wpos = wpos[0..130]
296
+
297
+ # vr = @view.visible_rect
298
+ # # gtk_text_view_get_line_at_y
299
+ # # gtk_text_view_get_iter_at_position
300
+ # gtk_text_view_get_iter_at_position(vr.
301
+ # istart = @view.get_iter_at_position(vr.x,vr.y)
302
+ # istart = @view.get_iter_at_y(vr.y)
303
+ # startpos = @view.get_iter_at_position_raw(vr.x,vr.y)[1].offset
304
+ # endpos = @view.get_iter_at_position_raw(vr.x+vr.width,vr.y+vr.height)[1].offset
305
+ # debug "startpos,endpos:#{[startpos, endpos]}"
306
+
307
+ da = @da
308
+ if false
309
+ da.signal_connect "draw" do |widget, cr|
310
+ cr.save
311
+ for pos in wpos
312
+ (x, y) = @view.pos_to_coord(pos)
313
+
314
+ layout = da.create_pango_layout("XY")
315
+ desc = Pango::FontDescription.new("sans bold 11")
316
+ layout.font_description = desc
317
+
318
+ cr.move_to(x, y)
319
+ # cr.move_to(gutter_width, 300)
320
+ cr.pango_layout_path(layout)
321
+
322
+ cr.set_source_rgb(1.0, 0.0, 0.0)
323
+ cr.fill_preserve
324
+ end
325
+ cr.restore
326
+ false # = draw other
327
+ # true # = Don't draw others
328
+ end
329
+ end
330
+
331
+ for pos in wpos
332
+ (x, y) = @view.pos_to_coord(pos)
333
+ # da.put(Gtk::Label.new("AB"), x, y)
334
+ label = Gtk::Label.new("<span background='#00000088' foreground='#ff0000' weight='ultrabold'>AB</span>")
335
+ label.use_markup = true
336
+ da.put(label, x, y)
337
+ end
338
+
339
+ # debug @view.pos_to_coord(300).inspect
340
+
341
+ @da.show_all
342
+ end
343
+
344
+ def handle_deltas()
345
+ while d = buf.deltas.shift
346
+ pos = d[0]
347
+ op = d[1]
348
+ num = d[2]
349
+ txt = d[3]
350
+ if op == DELETE
351
+ startiter = @buf1.get_iter_at(:offset => pos)
352
+ enditer = @buf1.get_iter_at(:offset => pos + num)
353
+ @buf1.delete(startiter, enditer)
354
+ elsif op == INSERT
355
+ startiter = @buf1.get_iter_at(:offset => pos)
356
+ @buf1.insert(startiter, txt)
357
+ end
358
+ end
359
+ end
360
+
361
+ def add_to_minibuf(msg)
362
+ startiter = @minibuf.buffer.get_iter_at(:offset => 0)
363
+ @minibuf.buffer.insert(startiter, "#{msg}\n")
364
+ @minibuf.signal_emit("move-cursor", Gtk::MovementStep.new(:PAGES), -1, false)
365
+ end
366
+
367
+ def init_minibuffer()
368
+ # Init minibuffer
369
+ sw = Gtk::ScrolledWindow.new
370
+ sw.set_policy(:automatic, :automatic)
371
+ overlay = Gtk::Overlay.new
372
+ overlay.add(sw)
373
+ # @vpaned.pack2(overlay, :resize => false)
374
+ @vbox.attach(overlay, 0, 2, 1, 1)
375
+ # overlay.set_size_request(-1, 50)
376
+ # $ovrl = overlay
377
+ # $ovrl.set_size_request(-1, 30)
378
+ $sw2 = sw
379
+ sw.set_size_request(-1, 12)
380
+
381
+ view = VSourceView.new()
382
+ view.set_highlight_current_line(false)
383
+ view.set_show_line_numbers(false)
384
+ # view.set_buffer(buf1)
385
+ ssm = GtkSource::StyleSchemeManager.new
386
+ ssm.set_search_path(ssm.search_path << ppath("styles/"))
387
+ sty = ssm.get_scheme("molokai_edit")
388
+ view.buffer.highlight_matching_brackets = false
389
+ view.buffer.style_scheme = sty
390
+ provider = Gtk::CssProvider.new
391
+ # provider.load(data: "textview { font-family: Monospace; font-size: 11pt; }")
392
+ provider.load(data: "textview { font-family: Arial; font-size: 10pt; color:#ff0000}")
393
+ view.style_context.add_provider(provider)
394
+ view.wrap_mode = :char
395
+ @minibuf = view
396
+ # Ripl.start :binding => binding
397
+ # startiter = view.buffer.get_iter_at(:offset => 0)
398
+ message("STARTUP")
399
+ sw.add(view)
400
+ end
401
+
402
+ def init_header_bar()
403
+ header = Gtk::HeaderBar.new
404
+ @header = header
405
+ header.show_close_button = true
406
+ header.title = ""
407
+ header.has_subtitle = true
408
+ header.subtitle = ""
409
+ # Ripl.start :binding => binding
410
+
411
+ # icon = Gio::ThemedIcon.new("mail-send-receive-symbolic")
412
+ # icon = Gio::ThemedIcon.new("document-open-symbolic")
413
+ # icon = Gio::ThemedIcon.new("dialog-password")
414
+
415
+ #edit-redo edit-paste edit-find-replace edit-undo edit-find edit-cut edit-copy
416
+ #document-open document-save document-save-as document-properties document-new
417
+ # document-revert-symbolic
418
+ #
419
+
420
+ #TODO:
421
+ # button = Gtk::Button.new
422
+ # icon = Gio::ThemedIcon.new("open-menu-symbolic")
423
+ # image = Gtk::Image.new(:icon => icon, :size => :button)
424
+ # button.add(image)
425
+ # header.pack_end(button)
426
+
427
+ button = Gtk::Button.new
428
+ icon = Gio::ThemedIcon.new("document-open-symbolic")
429
+ image = Gtk::Image.new(:icon => icon, :size => :button)
430
+ button.add(image)
431
+ header.pack_end(button)
432
+
433
+ button.signal_connect "clicked" do |_widget|
434
+ open_file_dialog
435
+ end
436
+
437
+ button = Gtk::Button.new
438
+ icon = Gio::ThemedIcon.new("document-save-symbolic")
439
+ image = Gtk::Image.new(:icon => icon, :size => :button)
440
+ button.add(image)
441
+ header.pack_end(button)
442
+ button.signal_connect "clicked" do |_widget|
443
+ buf.save
444
+ end
445
+
446
+ button = Gtk::Button.new
447
+ icon = Gio::ThemedIcon.new("document-new-symbolic")
448
+ image = Gtk::Image.new(:icon => icon, :size => :button)
449
+ button.add(image)
450
+ header.pack_end(button)
451
+ button.signal_connect "clicked" do |_widget|
452
+ create_new_file
453
+ end
454
+
455
+ box = Gtk::Box.new(:horizontal, 0)
456
+ box.style_context.add_class("linked")
457
+
458
+ button = Gtk::Button.new
459
+ image = Gtk::Image.new(:icon_name => "pan-start-symbolic", :size => :button)
460
+ button.add(image)
461
+ box.add(button)
462
+ button.signal_connect "clicked" do |_widget|
463
+ history_switch_backwards
464
+ end
465
+
466
+ button = Gtk::Button.new
467
+ image = Gtk::Image.new(:icon_name => "pan-end-symbolic", :size => :button)
468
+ button.add(image)
469
+ box.add(button)
470
+ button.signal_connect "clicked" do |_widget|
471
+ history_switch_forwards
472
+ end
473
+
474
+ button = Gtk::Button.new
475
+ icon = Gio::ThemedIcon.new("window-close-symbolic")
476
+ image = Gtk::Image.new(:icon => icon, :size => :button)
477
+ button.add(image)
478
+ box.add(button)
479
+ button.signal_connect "clicked" do |_widget|
480
+ bufs.close_current_buffer
481
+ end
482
+
483
+ header.pack_start(box)
484
+ @window.titlebar = header
485
+ @window.add(Gtk::TextView.new)
486
+ end
487
+
488
+ def create_menu_item(label, depth)
489
+ menuitem = Gtk::MenuItem.new(:label => label)
490
+ menuitem.submenu = create_menu(depth)
491
+ @menubar.append(menuitem)
492
+ end
493
+
494
+ def create_menu(depth)
495
+ return nil if depth < 1
496
+
497
+ menu = Gtk::Menu.new
498
+ last_item = nil
499
+ (0..5).each do |i|
500
+ j = i + 1
501
+ label = "item #{depth} - #{j}"
502
+ menu_item = Gtk::RadioMenuItem.new(nil, label)
503
+ menu_item.join_group(last_item) if last_item
504
+ last_item = menu_item
505
+ menu.append(menu_item)
506
+ menu_item.sensitive = false if i == 3
507
+ menu_item.submenu = create_menu(depth - 1)
508
+ end
509
+
510
+ menu
511
+ end
512
+
513
+ def init_window
514
+ @window = Gtk::Window.new(:toplevel)
515
+ @window.set_default_size(650, 850)
516
+ @window.title = "Multiple Views"
517
+ @window.show_all
518
+ # vpaned = Gtk::Paned.new(:horizontal)
519
+ @vpaned = Gtk::Paned.new(:vertical)
520
+ #@vpaned = Gtk::Box.new(:vertical, 0)
521
+ # @vbox = Gtk::Box.new(:vertical, 0)
522
+ @vbox = Gtk::Grid.new()
523
+ @window.add(@vbox)
524
+
525
+ @menubar = Gtk::MenuBar.new
526
+ @menubar.expand = false
527
+
528
+ @sw = Gtk::ScrolledWindow.new
529
+ @sw.set_policy(:automatic, :automatic)
530
+ @overlay = Gtk::Overlay.new
531
+ @overlay.add(@sw)
532
+
533
+ # @vpaned.pack1(@overlay, :resize => true)
534
+ # @vpaned.pack2(@menubar, :resize => false)
535
+ # @vbox.add(@menubar, :resize => false)
536
+
537
+ init_header_bar
538
+
539
+ # @window.show_all
540
+
541
+ # @vbox.pack_start(@menubar, :expand => false, :fill => false, :padding => 0 )
542
+ # @vbox.pack_start(@menubar)
543
+ # @vbox.pack_start(@overlay, :expand => true, :fill => true, :padding => 0 )
544
+ # @vbox.pack_start(@overlay, :expand => true, :fill => true, :padding => 0 )
545
+ @vbox.attach(@menubar, 0, 0, 1, 1)
546
+ @vbox.attach(@overlay, 0, 1, 1, 1)
547
+ @overlay.vexpand = true
548
+ @overlay.hexpand = true
549
+
550
+ @menubar.vexpand = false
551
+ @menubar.hexpand = false
552
+
553
+ init_minibuffer
554
+
555
+ @window.show_all
556
+ vma.start
557
+ Vimamsa::Menu.new(@menubar)
558
+ @window.show_all
559
+ end
560
+ end
@@ -0,0 +1,110 @@
1
+ module Vimamsa
2
+ class Menu
3
+ def add_to_menu(_mpath, x)
4
+ mpath = _mpath.split(".")
5
+ curnfo = @nfo
6
+ for y in mpath
7
+ debug(curnfo.inspect)
8
+ if y.equal?(mpath.last)
9
+ curnfo[y] = x
10
+ elsif curnfo[y].nil?
11
+ curnfo[y] = { :label => y, :items => {} }
12
+ end
13
+ curnfo[y][:items] = {} if curnfo[y][:items].class != Hash
14
+ curnfo = curnfo[y][:items]
15
+ end #end for
16
+ end
17
+
18
+ def add_menu_items()
19
+
20
+ add_to_menu "File.Example", { :label => "<span foreground='#888888'>Action, [mode] key binding</span>", :action => nil }
21
+ add_to_menu "File.Save", { :label => "Save", :action => :buf_save }
22
+ add_to_menu "File.Save as", { :label => "Save As...", :action => :buf_save_as }
23
+ add_to_menu "File.Open", { :label => "Open", :action => :open_file_dialog }
24
+
25
+ add_to_menu "File.New", { :label => "New file", :action => :buf_new }
26
+ add_to_menu "File.Revert", { :label => "Reload file from disk", :action => :buf_revert }
27
+ add_to_menu "File.List", { :label => "List open files", :action => :start_buf_manager }
28
+
29
+ add_to_menu "File.Quit", { :label => "Quit", :action => :quit }
30
+
31
+ add_to_menu "Edit.Undo", { :label => "Undo edit", :action => :edit_undo }
32
+ add_to_menu "Edit.Redo", { :label => "Redo edit", :action => :edit_redo }
33
+ add_to_menu "Edit.SearchReplace", { :label => "Search and replace", :action => :gui_search_replace }
34
+ add_to_menu "Edit.Find", { :label => "Find", :action => :find_in_buffer }
35
+
36
+ add_to_menu "Actions.SearchForActions", { :label => "Search for Actions", :action => :search_actions }
37
+
38
+ add_to_menu "Actions.Grep", { :label => "Grep lines", :action => :invoke_grep_search }
39
+
40
+ add_to_menu "Actions.FileHistoryFinder", { :label => "Search files in history", :action => :gui_file_history_finder }
41
+
42
+ add_to_menu "Actions.experimental.Diff", { :label => "Show Diff of\nunsaved changes", :action => :diff_buffer }
43
+
44
+ add_to_menu "Actions.experimental.EnableDebug", { :label => "Enable debug", :action => :enable_debug }
45
+ add_to_menu "Actions.experimental.DisableDebug", { :label => "Disable debug", :action => :disable_debug }
46
+ add_to_menu "Actions.experimental.ShowImages", { :label => "Show images ⟦img:path⟧", :action => :show_images }
47
+
48
+
49
+ add_to_menu "Actions.EncryptFile", { :label => "Encrypt file", :action => :encrypt_file }
50
+ add_to_menu "Help.KeyBindings", { :label => "Show key bindings", :action => :show_key_bindings }
51
+
52
+
53
+ #TODO: :auto_indent_buffer
54
+
55
+ # add_to_menu "Actions.Ack", { :label => "source code search (Ack)", :action => :ack_search }
56
+
57
+ end
58
+
59
+ def initialize(menubar)
60
+ # nfo["file"] = { :items => {}, :label => "File" }
61
+ # nfo["actions"] = { :items => {}, :label => "Actions" }
62
+ # nfo["help"] = { :items => {}, :label => "Help" }
63
+
64
+ @nfo = {}
65
+
66
+ add_menu_items
67
+
68
+ # add_to_menu("help.extra.keybindings", { :label => "Show keybindings" })
69
+ # add_to_menu("help.extra.nfo.keybindings", { :label => "Show keybindings" })
70
+ # add_to_menu("help.keybindings", { :label => "Show keybindings <span foreground='#888888' >C ? k</span>" }) #font='12' weight='ultrabold'
71
+
72
+ for k, v in @nfo
73
+ build_menu(v, menubar)
74
+ end
75
+ end
76
+
77
+ def build_menu(nfo, parent)
78
+ menu = Gtk::Menu.new
79
+ if nfo[:action]
80
+ kbd_str = ""
81
+ for mode_str in ["C", "V"]
82
+ c_kbd = vma.kbd.act_bindings[mode_str][nfo[:action]]
83
+ if c_kbd.class == String
84
+ kbd_str = " <span foreground='#888888'><span weight='bold'>[#{mode_str}]</span> #{c_kbd}</span>"
85
+ break
86
+ end
87
+ end
88
+
89
+ label_str = nfo[:label] + kbd_str
90
+ menuitem = Gtk::MenuItem.new(:label => label_str)
91
+ menuitem.children[0].set_markup(label_str)
92
+
93
+ menuitem.signal_connect("activate") do
94
+ call_action(nfo[:action])
95
+ end
96
+ else
97
+ menuitem = Gtk::MenuItem.new(:label => nfo[:label])
98
+ menuitem.children[0].set_markup(nfo[:label])
99
+ end
100
+
101
+ if !nfo[:items].nil? and !nfo[:items].empty?
102
+ for k2, item in nfo[:items]
103
+ build_menu(item, menu)
104
+ end
105
+ menuitem.submenu = menu
106
+ end
107
+ parent.append(menuitem)
108
+ end
109
+ end #end class
110
+ end