vimamsa 0.1.10 → 0.1.12

Sign up to get free protection for your applications and to get access to all the features.
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