vimamsa 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/vimamsa/gui.rb CHANGED
@@ -3,40 +3,42 @@ $idle_scroll_to_mark = false
3
3
  def gui_open_file_dialog(dirpath)
4
4
  dialog = Gtk::FileChooserDialog.new(:title => "Open file",
5
5
  :action => :open,
6
- :buttons => [[Gtk::Stock::OPEN, :accept],
7
- [Gtk::Stock::CANCEL, :cancel]])
8
- dialog.set_current_folder(dirpath)
6
+ :buttons => [["Open", :accept],
7
+ ["Cancel", :cancel]])
8
+ dialog.set_current_folder(Gio::File.new_for_path(dirpath))
9
+ # dialog.set_current_folder(Gio::File.new_for_path("/tmp"))
9
10
 
10
11
  dialog.signal_connect("response") do |dialog, response_id|
11
12
  if response_id == Gtk::ResponseType::ACCEPT
12
- open_new_file(dialog.filename)
13
- # debug "uri = #{dialog.uri}"
13
+ open_new_file(dialog.file.parse_name)
14
14
  end
15
15
  dialog.destroy
16
16
  end
17
- dialog.run
17
+
18
+ dialog.modal = true
19
+ dialog.show
18
20
  end
19
21
 
20
22
  def gui_file_saveas(dirpath)
21
23
  dialog = Gtk::FileChooserDialog.new(:title => "Save as",
22
24
  :action => :save,
23
- :buttons => [[Gtk::Stock::SAVE, :accept],
24
- [Gtk::Stock::CANCEL, :cancel]])
25
- dialog.set_current_folder(dirpath)
25
+ :buttons => [["Save", :accept],
26
+ ["Cancel", :cancel]])
27
+ # dialog.set_current_folder(dirpath) #TODO:gtk4
26
28
  dialog.signal_connect("response") do |dialog, response_id|
27
29
  if response_id == Gtk::ResponseType::ACCEPT
28
- file_saveas(dialog.filename)
30
+ file_saveas(dialog.file.parse_name)
29
31
  end
30
32
  dialog.destroy
31
33
  end
32
34
 
33
- dialog.run
35
+ dialog.modal = true
36
+ dialog.show
34
37
  end
35
38
 
36
39
  def idle_func
37
40
  # debug "IDLEFUNC"
38
41
  if $idle_scroll_to_mark
39
- # Ripl.start :binding => binding
40
42
  # $view.get_visible_rect
41
43
  vr = $view.visible_rect
42
44
 
@@ -46,7 +48,6 @@ def idle_func
46
48
  iter = b.get_iter_at(:offset => b.cursor_position)
47
49
  iterxy = $view.get_iter_location(iter)
48
50
  # debug "ITERXY" + iterxy.inspect
49
- # Ripl.start :binding => binding
50
51
 
51
52
  intr = iterxy.intersect(vr)
52
53
  if intr.nil?
@@ -90,21 +91,16 @@ def page_down
90
91
  end
91
92
 
92
93
  def paste_system_clipboard()
93
- # clipboard = $vmag.window.get_clipboard(Gdk::Selection::CLIPBOARD)
94
+
95
+ #TODO: Check if something useful in this old GTK3 code.
94
96
  utf8_string = Gdk::Atom.intern("UTF8_STRING")
95
- # x = clipboard.request_contents(utf8_string)
96
97
 
97
- widget = Gtk::Invisible.new
98
98
  clipboard = Gtk::Clipboard.get_default($vmag.window.display)
99
99
  received_text = ""
100
100
 
101
101
  target_string = Gdk::Selection::TARGET_STRING
102
102
  ti = clipboard.request_contents(target_string)
103
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
104
  if clipboard.wait_is_text_available?
109
105
  received_text = clipboard.wait_for_text
110
106
  end
@@ -123,12 +119,7 @@ def paste_system_clipboard()
123
119
  end
124
120
 
125
121
  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
122
+ vma.gui.window.display.clipboard.set(arg)
132
123
  end
133
124
 
134
125
  def gui_create_buffer(id, bufo)
@@ -136,6 +127,9 @@ def gui_create_buffer(id, bufo)
136
127
  buf1 = GtkSource::Buffer.new()
137
128
  view = VSourceView.new(nil, bufo)
138
129
 
130
+ view.register_signals()
131
+ $debug = true
132
+
139
133
  ssm = GtkSource::StyleSchemeManager.new
140
134
  ssm.set_search_path(ssm.search_path << ppath("styles/"))
141
135
  sty = ssm.get_scheme("molokai_edit")
@@ -179,73 +173,69 @@ def gui_set_buffer_contents(id, txt)
179
173
  vma.gui.buffers[id].buffer.set_text(txt)
180
174
  end
181
175
 
176
+ #TODO: remove
182
177
  def gui_set_cursor_pos(id, pos)
183
178
  vma.buf.view.set_cursor_pos(pos)
184
179
  end
185
180
 
186
181
  def gui_set_current_buffer(id)
187
- view = $vmag.buffers[id]
188
- debug "gui_set_current_buffer(#{id}), view=#{view}"
189
- buf1 = view.buffer
190
- $vmag.view = view
191
- $vmag.buf1 = buf1
192
- $view = view
193
- $vbuf = buf1
194
-
195
- $vmag.sw.remove($vmag.sw.child) if !$vmag.sw.child.nil?
196
- $vmag.sw.add(view)
197
-
198
- view.grab_focus
199
- view.set_cursor_visible(true)
200
- view.place_cursor_onscreen
201
-
202
- $vmag.sw.show_all
182
+ vma.gui.set_current_buffer(id)
183
+ return
203
184
  end
204
185
 
205
186
  def gui_set_window_title(wtitle, subtitle = "")
206
187
  $vmag.window.title = wtitle
207
- $vmag.window.titlebar.subtitle = subtitle
188
+ # $vmag.subtitle.markup = "<span weight='ultrabold'>#{subtitle}</span>"
189
+ $vmag.subtitle.markup = "<span weight='light' size='small'>#{subtitle}</span>"
190
+ # $vmag.window.titlebar.subtitle = subtitle #TODO:gtk4
208
191
  end
209
192
 
210
193
  class VMAgui
211
- attr_accessor :buffers, :sw, :view, :buf1, :window, :delex, :statnfo
212
-
213
- VERSION = "1.0"
214
-
215
- HEART = "♥"
216
- RADIUS = 150
217
- N_WORDS = 5
218
- FONT = "Serif 18"
219
- TEXT = "I ♥ GTK+"
194
+ attr_accessor :buffers, :sw, :sw1, :sw2, :view, :buf1, :window, :delex, :statnfo, :overlay, :overlay1, :overlay2, :sws, :two_c
195
+ attr_reader :two_column, :windows, :subtitle, :app
220
196
 
221
197
  def initialize()
198
+ @two_column = false
199
+ @active_column = 1
222
200
  @show_overlay = true
223
201
  @da = nil
202
+ @sws = []
224
203
  @buffers = {}
225
204
  @view = nil
226
205
  @buf1 = nil
227
206
  @img_resizer_active = false
228
- imgproc = proc {
229
- GLib::Idle.add(proc {
230
- if !buf.images.empty?
231
- vma.gui.scale_all_images
232
-
233
- w = Gtk::Window.new(:toplevel)
234
- w.set_default_size(1, 1)
235
- w.show_all
236
- Thread.new { sleep 0.1; w.destroy }
237
- end
238
-
239
- false
240
- })
241
- }
242
- @delex = DelayExecutioner.new(1, imgproc)
207
+ @windows = {}
208
+ @app = nil
209
+ # imgproc = proc {
210
+ # GLib::Idle.add(proc {
211
+ # if !buf.images.empty?
212
+ # vma.gui.scale_all_images
213
+
214
+ # w = Gtk::Window.new(:toplevel)
215
+ # w.set_default_size(1, 1)
216
+ # w.show_all
217
+ # Thread.new { sleep 0.1; w.destroy }
218
+ # end
219
+
220
+ # false
221
+ # })
222
+ # }
223
+ # @delex = DelayExecutioner.new(1, imgproc)
243
224
  end
244
225
 
245
226
  def run
246
227
  init_window
247
228
  # init_rtext
248
- Gtk.main
229
+ end
230
+
231
+ def quit
232
+ @window.destroy
233
+ @shutdown = true
234
+ for t in Thread.list
235
+ if t != Thread.current
236
+ t.exit
237
+ end
238
+ end
249
239
  end
250
240
 
251
241
  def delay_scale()
@@ -254,22 +244,21 @@ class VMAgui
254
244
  end
255
245
 
256
246
  def scale_all_images
257
- # puts "scale all"
247
+ debug "scale all", 2
258
248
  for img in buf.images
259
249
  if !img[:obj].destroyed?
260
250
  img[:obj].scale_image
261
251
  end
262
252
  end
253
+ false
263
254
  end
264
255
 
265
- def handle_image_resize
256
+ def handle_image_resize #TODO:gtk4
266
257
  return if @img_resizer_active == true
267
258
  @dtime = Time.now
268
259
 
269
260
  $gcrw = 0
270
261
  vma.gui.window.signal_connect "configure-event" do |widget, cr|
271
- # Ripl.start :binding => binding
272
-
273
262
  if $gcrw != cr.width
274
263
  @delex.run
275
264
  end
@@ -283,12 +272,14 @@ class VMAgui
283
272
  def start_overlay_draw()
284
273
  @da = Gtk::Fixed.new
285
274
  @overlay.add_overlay(@da)
286
- @overlay.set_overlay_pass_through(@da, true)
275
+
276
+ # @overlay.set_overlay_pass_through(@da, true) #TODO:gtk4
287
277
  end
288
278
 
289
279
  def clear_overlay()
290
280
  if @da != nil
291
- @overlay.remove(@da)
281
+ # @overlay.remove(@da)
282
+ @overlay.remove_overlay(@da)
292
283
  end
293
284
  end
294
285
 
@@ -302,72 +293,56 @@ class VMAgui
302
293
  end
303
294
 
304
295
  def end_overlay_draw()
305
- @da.show_all
296
+ @da.show
306
297
  end
307
298
 
308
- def toggle_overlay
309
- @show_overlay = @show_overlay ^ 1
310
- if !@show_overlay
311
- if @da != nil
312
- @overlay.remove(@da)
313
- end
314
- return
315
- else
316
- @da = Gtk::Fixed.new
317
- @overlay.add_overlay(@da)
318
- @overlay.set_overlay_pass_through(@da, true)
299
+ def remove_overlay_cursor()
300
+ if !@cursorov.nil?
301
+ @overlay.remove_overlay(@cursorov)
302
+ @cursorov = nil
319
303
  end
304
+ end
320
305
 
321
- (startpos, endpos) = get_visible_area
322
- s = @view.buffer.text
323
- wpos = s.enum_for(:scan, /\W(\w)/).map { Regexp.last_match.begin(0) + 1 }
324
- wpos = wpos[0..130]
325
-
326
- # vr = @view.visible_rect
327
- # # gtk_text_view_get_line_at_y
328
- # # gtk_text_view_get_iter_at_position
329
- # gtk_text_view_get_iter_at_position(vr.
330
- # istart = @view.get_iter_at_position(vr.x,vr.y)
331
- # istart = @view.get_iter_at_y(vr.y)
332
- # startpos = @view.get_iter_at_position_raw(vr.x,vr.y)[1].offset
333
- # endpos = @view.get_iter_at_position_raw(vr.x+vr.width,vr.y+vr.height)[1].offset
334
- # debug "startpos,endpos:#{[startpos, endpos]}"
335
-
336
- da = @da
337
- if false
338
- da.signal_connect "draw" do |widget, cr|
339
- cr.save
340
- for pos in wpos
341
- (x, y) = @view.pos_to_coord(pos)
342
-
343
- layout = da.create_pango_layout("XY")
344
- desc = Pango::FontDescription.new("sans bold 11")
345
- layout.font_description = desc
346
-
347
- cr.move_to(x, y)
348
- # cr.move_to(gutter_width, 300)
349
- cr.pango_layout_path(layout)
350
-
351
- cr.set_source_rgb(1.0, 0.0, 0.0)
352
- cr.fill_preserve
353
- end
354
- cr.restore
355
- false # = draw other
356
- # true # = Don't draw others
306
+ def overlay_draw_cursor(textpos)
307
+ # return
308
+ remove_overlay_cursor
309
+ GLib::Idle.add(proc { self.overlay_draw_cursor_(textpos) })
310
+ # overlay_draw_cursor_(textpos)
311
+ end
312
+
313
+ # Run proc after animated scrolling has stopped (e.g. after page down)
314
+ def run_after_scrolling(p)
315
+ Thread.new {
316
+ while Time.now - @last_adj_time < 0.1
317
+ sleep 0.1
357
318
  end
358
- end
319
+ run_as_idle p
320
+ }
321
+ end
359
322
 
360
- for pos in wpos
361
- (x, y) = @view.pos_to_coord(pos)
362
- # da.put(Gtk::Label.new("AB"), x, y)
363
- label = Gtk::Label.new("<span background='#00000088' foreground='#ff0000' weight='ultrabold'>AB</span>")
364
- label.use_markup = true
365
- da.put(label, x, y)
366
- end
323
+ # To draw on empty lines and line-ends (where select_range doesn't work)
324
+ def overlay_draw_cursor_(textpos)
325
+ # Thread.new {
326
+ # GLib::Idle.add(proc { p.call; false })
327
+ # }
328
+
329
+ # while Time.now - @last_adj_time < 0.3
330
+ # return true
331
+ # end
367
332
 
368
- # debug @view.pos_to_coord(300).inspect
333
+ remove_overlay_cursor
334
+ @cursorov = Gtk::Fixed.new
335
+ @overlay.add_overlay(@cursorov)
369
336
 
370
- @da.show_all
337
+ (x, y) = @view.pos_to_coord(textpos)
338
+ pp [x, y]
339
+
340
+ # Trying to draw only background of character "I"
341
+ label = Gtk::Label.new("<span background='#00ffaaff' foreground='#00ffaaff' weight='ultrabold'>I</span>")
342
+ label.use_markup = true
343
+ @cursorov.put(label, x, y)
344
+ @cursorov.show
345
+ return false
371
346
  end
372
347
 
373
348
  def handle_deltas()
@@ -388,6 +363,7 @@ class VMAgui
388
363
  end
389
364
 
390
365
  def add_to_minibuf(msg)
366
+ # return #TODO:gtk4
391
367
  startiter = @minibuf.buffer.get_iter_at(:offset => 0)
392
368
  @minibuf.buffer.insert(startiter, "#{msg}\n")
393
369
  @minibuf.signal_emit("move-cursor", Gtk::MovementStep.new(:PAGES), -1, false)
@@ -398,12 +374,8 @@ class VMAgui
398
374
  sw = Gtk::ScrolledWindow.new
399
375
  sw.set_policy(:automatic, :automatic)
400
376
  overlay = Gtk::Overlay.new
401
- overlay.add(sw)
402
- # @vpaned.pack2(overlay, :resize => false)
403
- @vbox.attach(overlay, 0, 2, 2, 1)
404
- # overlay.set_size_request(-1, 50)
405
- # $ovrl = overlay
406
- # $ovrl.set_size_request(-1, 30)
377
+ overlay.set_child(sw)
378
+ @vbox.attach(overlay, 0, 3, 2, 1)
407
379
  $sw2 = sw
408
380
  sw.set_size_request(-1, 12)
409
381
 
@@ -418,22 +390,21 @@ class VMAgui
418
390
  view.buffer.style_scheme = sty
419
391
  provider = Gtk::CssProvider.new
420
392
  # provider.load(data: "textview { font-family: Monospace; font-size: 11pt; }")
421
- provider.load(data: "textview { font-family: Arial; font-size: 10pt; color:#ff0000}")
393
+ provider.load(data: "textview { font-family: Arial; font-size: 10pt; color:#eeeeee}")
422
394
  view.style_context.add_provider(provider)
423
395
  view.wrap_mode = :char
424
396
  @minibuf = view
425
- # Ripl.start :binding => binding
426
397
  # startiter = view.buffer.get_iter_at(:offset => 0)
427
398
  message("STARTUP")
428
- sw.add(view)
399
+ sw.set_child(view)
429
400
  end
430
401
 
431
402
  def init_header_bar()
432
403
  header = Gtk::HeaderBar.new
433
404
  @header = header
434
405
  header.show_close_button = true
435
- header.title = ""
436
- header.has_subtitle = true
406
+ # header.title = ""#TODO:gtk4
407
+ # header.has_subtitle = true#TODO:gtk4
437
408
  header.subtitle = ""
438
409
 
439
410
  # icon = Gio::ThemedIcon.new("mail-send-receive-symbolic")
@@ -513,55 +484,422 @@ class VMAgui
513
484
  # @window.add(Gtk::TextView.new)
514
485
  end
515
486
 
487
+ def debug_idle_func
488
+ return false if @shutdown == true
489
+ if Time.now - @last_debug_idle > 1
490
+ @last_debug_idle = Time.now
491
+ # puts "DEBUG IDLE #{Time.now}"
492
+ # @view.check_controllers
493
+ end
494
+
495
+ ctrl_fn = File.expand_path("~/.vimamsa/ripl_ctrl")
496
+ # Allows to debug in case keyboard handling is lost
497
+ if File.exist?(ctrl_fn)
498
+ File.delete(ctrl_fn)
499
+ start_ripl
500
+ end
501
+
502
+ sleep 0.02
503
+ return true
504
+ end
505
+
506
+ # Remove widget event controllers added by gtk, and add our own.
507
+ def reset_controllers
508
+ clist = @window.observe_controllers
509
+ to_remove = []
510
+ (0..(clist.n_items - 1)).each { |x|
511
+ ctr = clist.get_item(x)
512
+ if ctr.class == Gtk::EventControllerKey
513
+ to_remove << ctr
514
+ end
515
+ }
516
+ if to_remove.size > 0
517
+ puts "Removing controllers:"
518
+ pp to_remove
519
+ to_remove.each { |x| @window.remove_controller(x) }
520
+ end
521
+
522
+ press = Gtk::EventControllerKey.new
523
+ @press = press
524
+ # to prevent SourceView key handler capturing any keypresses
525
+ press.set_propagation_phase(Gtk::PropagationPhase::CAPTURE)
526
+ @window.add_controller(press)
527
+
528
+ press.signal_connect "key-pressed" do |gesture, keyval, keycode, y|
529
+ name = Gdk::Keyval.to_name(keyval)
530
+ uki = Gdk::Keyval.to_unicode(keyval)
531
+ keystr = uki.chr("UTF-8")
532
+ puts "key-pressed #{keyval} #{keycode} name:#{name} str:#{keystr} unicode:#{uki}"
533
+ buf.view.handle_key_event(keyval, keystr, :key_press)
534
+ true
535
+ end
536
+
537
+ press.signal_connect "modifiers" do |eventctr, modtype|
538
+ # eventctr: Gtk::EventControllerKey
539
+ # modtype: Gdk::ModifierType
540
+ debug "modifier change"
541
+ vma.kbd.modifiers[:ctrl] = modtype.control_mask?
542
+ vma.kbd.modifiers[:alt] = modtype.alt_mask?
543
+ vma.kbd.modifiers[:hyper] = modtype.hyper_mask?
544
+ vma.kbd.modifiers[:lock] = modtype.lock_mask?
545
+ vma.kbd.modifiers[:meta] = modtype.meta_mask?
546
+ vma.kbd.modifiers[:shift] = modtype.shift_mask?
547
+ vma.kbd.modifiers[:super] = modtype.super_mask?
548
+
549
+ #TODO:?
550
+ # button1_mask?
551
+ # ...
552
+ # button5_mask?
553
+ true
554
+ end
555
+
556
+ press.signal_connect "key-released" do |gesture, keyval, keycode, y|
557
+ name = Gdk::Keyval.to_name(keyval)
558
+ uki = Gdk::Keyval.to_unicode(keyval)
559
+ keystr = uki.chr("UTF-8")
560
+ puts "key released #{keyval} #{keycode} name:#{name} str:#{keystr} unicode:#{uki}"
561
+ buf.view.handle_key_event(keyval, keystr, :key_release)
562
+ # vma.kbd.match_key_conf(keystr, nil, :key_press)
563
+ # buf.view.handle_deltas
564
+ # buf.view.handle_key_event(keyval, keystr, :key_press)
565
+ true
566
+ end
567
+ end
568
+
569
+ def remove_extra_controllers
570
+ clist = vma.gui.window.observe_controllers
571
+ to_remove = []
572
+ (0..(clist.n_items - 1)).each { |x|
573
+ ctr = clist.get_item(x)
574
+ if ctr.class == Gtk::EventControllerKey and ctr != @press
575
+ to_remove << ctr
576
+ end
577
+ }
578
+ if to_remove.size > 0
579
+ puts "Removing controllers:"
580
+ pp to_remove
581
+ to_remove.each { |x| vma.gui.window.remove_controller(x) }
582
+ end
583
+ end
584
+
585
+ def idle_set_size()
586
+ # Need to wait for a while to window to be maximized to get correct @window.width
587
+ sleep 0.1
588
+ width = @window.width / 2
589
+ height = @window.height - 5
590
+ # Ripl.start :binding => binding
591
+ @window.unmaximize
592
+ @window.set_size_request(width, height)
593
+ return false
594
+ end
595
+
516
596
  def init_window
517
- @window = Gtk::Window.new(:toplevel)
518
- sh = @window.screen.height
519
- sw = @window.screen.width
520
- # TODO:Maximise vertically
521
- @window.set_default_size((sw * 0.45).to_i, sh - 20)
597
+ @last_debug_idle = Time.now
598
+ app = Gtk::Application.new("net.samiddhi.vimamsa.r#{rand(1000)}", :flags_none)
599
+ @app = app
600
+
601
+ Gtk::Settings.default.gtk_application_prefer_dark_theme = true
602
+ Gtk::Settings.default.gtk_theme_name = "Adwaita"
603
+
604
+ app.signal_connect "activate" do
605
+ @window = Gtk::ApplicationWindow.new(app)
606
+ @window.set_application(app)
607
+
608
+ @window.maximize
609
+ # Need to let Gtk process after maximize
610
+ run_as_idle proc { idle_set_size }
611
+
612
+ @window.title = "Multiple Views"
613
+ @vpaned = Gtk::Paned.new(:vertical)
614
+
615
+ @vbox = Gtk::Grid.new()
616
+ @window.add(@vbox)
617
+
618
+ Thread.new {
619
+ GLib::Idle.add(proc { debug_idle_func })
620
+ }
621
+
622
+ reset_controllers
623
+
624
+ @sw = Gtk::ScrolledWindow.new
625
+ @sw.set_policy(:automatic, :automatic)
626
+
627
+ @last_adj_time = Time.now
628
+ @sw.vadjustment.signal_connect("value-changed") { |x|
629
+ # pp x.page_increment
630
+ # pp x.page_size
631
+ # pp x.step_increment
632
+ # pp x.upper
633
+ # pp x.value
634
+ # pp x
635
+ @last_adj_time = Time.now
636
+ # puts "@sw.vadjustment"
637
+ }
638
+
639
+ # @sw.signal_connect("clicked") { puts "Hello World!" }
640
+ # @sw.signal_connect("key-pressed") { puts "Hello World!" }
641
+ @overlay = Gtk::Overlay.new
642
+ # @overlay.add(@sw) #TODO:gtk4
643
+ @overlay.add_overlay(@sw) #TODO:gtk4
644
+ @overlay1 = @overlay
645
+
646
+ # init_header_bar #TODO:gtk4
647
+
648
+ @statnfo = Gtk::Label.new
649
+ @subtitle = Gtk::Label.new("")
650
+ @statbox = Gtk::Box.new(:horizontal, 2)
651
+ @statnfo.set_size_request(150, 10)
652
+ @statbox.pack_end(@subtitle, :expand => true, :fill => true, :padding => 0)
653
+ @statbox.pack_end(@statnfo, :expand => false, :fill => false, :padding => 0)
654
+ provider = Gtk::CssProvider.new
655
+ @statnfo.add_css_class("statnfo")
656
+ provider.load(data: "label.statnfo { background-color:#353535; font-size: 10pt; margin-top:2px; margin-bottom:2px; align:right;}")
657
+
658
+ provider = Gtk::CssProvider.new
659
+ @statnfo.style_context.add_provider(provider)
660
+
661
+ # numbers: left, top, width, height
662
+ @vbox.attach(@overlay, 0, 2, 2, 1)
663
+ @sw.vexpand = true
664
+ @sw.hexpand = true
665
+
666
+ # column, row, width height
667
+ @vbox.attach(@statbox, 1, 1, 1, 1)
668
+
669
+ @overlay.vexpand = true
670
+ @overlay.hexpand = true
671
+
672
+ init_minibuffer
673
+
674
+ # p = Gtk::Popover.new
675
+
676
+ name = "save"
677
+ window = @window
678
+ action = Gio::SimpleAction.new(name)
679
+ action.signal_connect "activate" do |_simple_action, _parameter|
680
+ dialog = Gtk::MessageDialog.new(:parent => window,
681
+ :flags => :destroy_with_parent,
682
+ :buttons => :close,
683
+ :message => "Action FOOBAR activated.")
684
+ dialog.signal_connect(:response) do
685
+ dialog.destroy
686
+ end
687
+ dialog.show
688
+ end
522
689
 
523
- @window.title = "Multiple Views"
524
- @window.show_all
525
- @vpaned = Gtk::Paned.new(:vertical)
690
+ @window.add_action(action)
691
+ doc_actions = Gio::SimpleActionGroup.new
692
+ doc_actions.add_action(action)
526
693
 
527
- @vbox = Gtk::Grid.new()
528
- @window.add(@vbox)
694
+ act_quit = Gio::SimpleAction.new("quit")
695
+ app.add_action(act_quit)
696
+ act_quit.signal_connect "activate" do |_simple_action, _parameter|
697
+ window.destroy
698
+ exit!
699
+ end
529
700
 
530
- @menubar = Gtk::MenuBar.new
531
- @menubar.expand = false
701
+ menubar = Gio::Menu.new
702
+ app.menubar = menubar
703
+ @window.show_menubar = true
532
704
 
533
- @sw = Gtk::ScrolledWindow.new
534
- @sw.set_policy(:automatic, :automatic)
535
- @overlay = Gtk::Overlay.new
536
- @overlay.add(@sw)
705
+ @menubar = menubar
537
706
 
538
- init_header_bar
707
+ @windows[1] = { :sw => @sw, :overlay => @overlay, :id => 1 }
708
+ @active_window = @windows[1]
539
709
 
540
- @statnfo = Gtk::Label.new
541
- provider = Gtk::CssProvider.new
542
- provider.load(data: "textview { background-color:#353535; font-family: Monospace; font-size: 10pt; margin-top:4px;}")
543
- @statnfo.style_context.add_provider(provider)
710
+ @window.show
711
+
712
+ press = Gtk::GestureClick.new
713
+ press.button = Gdk::BUTTON_SECONDARY
714
+ @window.add_controller(press)
715
+ press.signal_connect "pressed" do |gesture, n_press, x, y|
716
+ puts "FOOBARpressed"
717
+ # clear_surface(surface)
718
+ # drawing_area.queue_draw
719
+ end
720
+ @sw1 = @sw
721
+
722
+ prov = Gtk::CssProvider.new
723
+ # See gtk-4.9.4/gtk/theme/Default/_common.scss on how to theme
724
+ # gtksourceview/gtksourcestyleschemepreview.c
725
+ # gtksourceview/gtksourcestylescheme.c
726
+ prov.load(data: " headerbar { padding: 0 0px; min-height: 16px; border-width: 0 0 0px; border-style: solid; }
727
+
728
+ textview border.left gutter { color: #8aa; font-size:8pt; }
729
+
730
+ textview border.left gutter { padding: 0px 0px 0px 0px; margin: 0px 0px 0px 0px; color: #8aa; font-size:9pt; }
731
+
732
+ headerbar .title {
733
+ font-weight: bold;
734
+ font-size: 11pt;
735
+ color: #cdffee;
736
+ }
737
+
738
+ headerbar > windowhandle > box .start {
739
+ border-spacing: 6px;
740
+ }
741
+
742
+ headerbar windowcontrols button {
743
+ min-height: 15px;
744
+ min-width: 15px;
745
+ }
746
+
747
+ ")
748
+ @window.style_context.add_provider(prov)
749
+
750
+ sc = Gtk::StyleContext.add_provider_for_display(Gdk::Display.default, prov)
751
+
752
+ vma.start
753
+ end
754
+
755
+ # Vimamsa::Menu.new(@menubar) #TODO:gtk4
756
+ app.run
757
+
758
+ # @window.show_all
759
+ # @window.show
760
+ end
761
+
762
+ def init_menu
763
+ Vimamsa::Menu.new(@menubar, @app)
764
+ end
765
+
766
+ def set_two_column
767
+ return if @two_column
768
+ # @window.set_default_size(800, 600) #TODO:gtk4
769
+ # @vpaned = Gtk::Paned.new(:vertical)
770
+ # @vbox = Gtk::Grid.new()
771
+ # @window.add(@vbox)
772
+
773
+ @sw2 = Gtk::ScrolledWindow.new
774
+ @sw2.set_policy(:automatic, :automatic)
775
+ @overlay2 = Gtk::Overlay.new
776
+ @overlay2.add_overlay(@sw2)
777
+ @pane = Gtk::Paned.new(:horizontal)
778
+
779
+ @windows[2] = { :sw => @sw2, :overlay => @overlay2, :id => 2 }
780
+
781
+ @vbox.remove(@overlay)
782
+
783
+ # numbers: left, top, width, height
784
+ @pane.set_start_child(@overlay2)
785
+ @pane.set_end_child(@overlay)
786
+
787
+ @vbox.attach(@pane, 0, 2, 2, 1)
788
+
789
+ @sw2.vexpand = true
790
+ @sw2.hexpand = true
791
+
792
+ @overlay2.vexpand = true
793
+ @overlay2.hexpand = true
794
+
795
+ @sw2.show
796
+ @two_column = true
797
+
798
+ if vma.buffers.size > 1
799
+ last = vma.buffers.get_last_visited_id
800
+ set_buffer_to_window(last, 2)
801
+ else
802
+ bf = create_new_buffer "\n\n", "buff", false
803
+ set_buffer_to_window(bf.id, 2)
804
+ end
805
+ end
544
806
 
545
- # Deprecated, but found no other way to do it. css doesn't work.
546
- # TODO: should select color automatically from theme
547
- @statnfo.override_background_color(Gtk::StateFlags::NORMAL, "#353535")
807
+ def is_buffer_open(bufid)
808
+ openbufids = @windows.keys.collect { |x| @windows[x][:sw].child.bufo.id }
809
+ return openbufids.include?(bufid)
810
+ end
811
+
812
+ def toggle_active_window()
813
+ return if !@two_column
814
+ if @active_column == 1
815
+ set_active_window(2)
816
+ else
817
+ set_active_window(1)
818
+ end
819
+ end
548
820
 
549
- # column, row, width height
550
- @vbox.attach(@menubar, 0, 0, 1, 1)
551
- @vbox.attach(@statnfo, 1, 0, 1, 1)
552
- @vbox.attach(@overlay, 0, 1, 2, 1)
553
- @overlay.vexpand = true
554
- @overlay.hexpand = true
821
+ # activate that window which has the given view
822
+ def set_current_view(view)
823
+ w = @windows.find { |k, v| v[:sw].child == view }
824
+ if !w.nil?
825
+ set_active_window(w[0])
826
+ end
827
+ end
555
828
 
556
- @menubar.vexpand = false
557
- @menubar.hexpand = false
829
+ def set_active_window(id)
830
+ return if !@two_column
831
+ return if id == @active_column
832
+ return if id == @active_window[:id]
558
833
 
559
- init_minibuffer
834
+ if @windows[id].nil?
835
+ debug "No such window #{id}", 2
836
+ return
837
+ end
838
+
839
+ @active_window = @windows[id]
840
+ @active_column = id #TODO: remove
841
+
842
+ @sw = @windows[id][:sw]
843
+ @overlay = @windows[id][:overlay]
844
+
845
+ vma.buffers.set_current_buffer_by_id(@sw.child.bufo.id)
846
+
847
+ #TODO: set buf & view of active window??
848
+
849
+ end
560
850
 
561
- @window.show_all
562
- vma.start
563
- Vimamsa::Menu.new(@menubar)
851
+ def current_view
852
+ return @sw.child
853
+ end
854
+
855
+ def set_buffer_to_window(bufid, winid)
856
+ view = @buffers[bufid]
857
+ debug "vma.gui.set_buffer_to_window(#{bufid}), winid=#{winid}"
858
+ buf1 = view.buffer
859
+
860
+ @windows[winid][:sw].set_child(view)
861
+ idle_ensure_cursor_drawn
862
+
863
+ # @overlay = Gtk::Overlay.new
864
+ # @overlay.add_overlay(view)
865
+
866
+ #TODO:???
867
+ # @view = view
868
+ # @buf1 = buf1
869
+ # $view = view ???
870
+ # $vbuf = buf1
871
+
872
+ end
873
+
874
+ def set_current_buffer(id)
875
+ view = @buffers[id]
876
+ debug "vma.gui.set_current_buffer(#{id}), view=#{view}"
877
+ buf1 = view.buffer
878
+ @view = view
879
+ @buf1 = buf1
880
+ $view = view
881
+ $vbuf = buf1
882
+
883
+ # Check if buffer is already open in another column
884
+ if @two_column and @active_column == 2 and id == @sw1.child.bufo.id
885
+ toggle_active_window
886
+ elsif @two_column && @active_column == 1 && !@sw2.child.nil? && id == @sw2.child.bufo.id
887
+ #TODO: should not need !@sw2.child.nil? here. If this happens then other column is empty.
888
+ toggle_active_window
889
+ else
890
+ @sw.set_child(view)
891
+ end
892
+ view.grab_focus
893
+
894
+ idle_ensure_cursor_drawn
895
+ end
896
+
897
+ def idle_ensure_cursor_drawn
898
+ run_as_idle proc { self.ensure_cursor_drawn }
899
+ end
564
900
 
565
- @window.show_all
901
+ def ensure_cursor_drawn
902
+ # view.place_cursor_onscreen #TODO: needed?
903
+ view.draw_cursor
566
904
  end
567
905
  end