topinambour 1.0.16 → 2.0.0

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/notebook.rb DELETED
@@ -1,109 +0,0 @@
1
- # Copyright 2015-2017 Cedric LE MOIGNE, cedlemo@gmx.com
2
- # This file is part of Topinambour.
3
- #
4
- # Topinambour is free software: you can redistribute it and/or modify
5
- # it under the terms of the GNU General Public License as published by
6
- # the Free Software Foundation, either version 3 of the License, or
7
- # any later version.
8
- #
9
- # Topinambour is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU General Public License
15
- # along with Topinambour. If not, see <http://www.gnu.org/licenses/>.
16
- class TopinambourNotebook < Gtk::Notebook
17
- attr_reader :visible, :hidden
18
-
19
- def initialize
20
- super()
21
- @hidden = []
22
- signal_connect("hide") { @visible = false }
23
-
24
- signal_connect("show") { @visible = true }
25
-
26
- signal_connect "switch-page" do |_widget, next_page, next_page_num|
27
- toplevel.current_label.text = next_page.term.terminal_title
28
- toplevel.current_tab.text = "#{next_page_num + 1}/#{n_pages}"
29
- generate_tab_preview if page >= 0
30
- end
31
-
32
- signal_connect "page-reordered" do
33
- toplevel.current_tab.text = "#{page + 1}/#{n_pages}"
34
- end
35
-
36
- signal_connect "page-removed" do |_widget, _child, page_num|
37
- if toplevel.class == TopinambourWindow
38
- toplevel.current_tab.text = "#{page + 1}/#{n_pages}"
39
- end
40
- end
41
- set_name("topinambour-notebook")
42
- set_show_tabs(false)
43
- set_show_border(false)
44
- end
45
-
46
- def remove_all_pages
47
- each do |widget|
48
- index = page_num(widget)
49
- remove_page(index)
50
- end
51
- end
52
-
53
- def cycle_next_page
54
- page < (n_pages - 1) ? next_page : set_page(0)
55
- end
56
-
57
- def cycle_prev_page
58
- page > 0 ? prev_page : set_page(n_pages - 1)
59
- end
60
-
61
- def current
62
- get_nth_page(page)
63
- end
64
-
65
- def remove_current_page
66
- if n_pages == 1
67
- if @hidden.empty?
68
- toplevel.quit_gracefully
69
- else
70
- append_page(@hidden.pop)
71
- remove_current_page
72
- end
73
- else
74
- remove(current)
75
- current.term.grab_focus
76
- end
77
- end
78
-
79
- def toggle_visibility
80
- @visible ? hide : show
81
- end
82
-
83
- def generate_tab_preview
84
- _x, _y, w, h = current.term.allocation.to_a
85
- surface = Cairo::ImageSurface.new(Cairo::FORMAT_ARGB32,
86
- w, h)
87
- cr = Cairo::Context.new(surface)
88
- current.term.draw(cr)
89
- pix = surface.to_pixbuf(:src_x => 0, :src_y => 0, :width => w, :height => h)
90
- current.term.preview = pix if pix
91
- end
92
-
93
- def send_to_all_terminals(method_name, values)
94
- each do |tab|
95
- tab.term.send(method_name, *values)
96
- end
97
- end
98
-
99
- def hide(index)
100
- child = get_nth_page(index)
101
- @hidden << child
102
- remove_page(index)
103
- end
104
-
105
- def unhide(index)
106
- append_page(@hidden.delete_at(index))
107
- toplevel.current_tab.text = "#{current_page + 1}/#{n_pages}"
108
- end
109
- end
data/lib/searchbar.rb DELETED
@@ -1,51 +0,0 @@
1
- # Copyright 2016 Cedric LE MOIGNE, cedlemo@gmx.com
2
- # This file is part of Topinambour.
3
- #
4
- # Topinambour is free software: you can redistribute it and/or modify
5
- # it under the terms of the GNU General Public License as published by
6
- # the Free Software Foundation, either version 3 of the License, or
7
- # any later version.
8
- #
9
- # Topinambour is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU General Public License
15
- # along with Topinambour. If not, see <http://www.gnu.org/licenses/>.
16
-
17
- class TopinambourSearchBar < Gtk::SearchBar
18
- def initialize(window)
19
- super()
20
-
21
- generate_search_entry(window)
22
- set_halign(:center)
23
- set_valign(:start)
24
- set_hexpand(false)
25
- set_vexpand(true)
26
- connect_entry(@entry)
27
- set_show_close_button = true
28
- add(@entry)
29
- end
30
-
31
- def generate_search_entry(window)
32
- @entry = Gtk::SearchEntry.new
33
- term = window.notebook.current.term
34
- @entry.signal_connect "next-match" do |entry|
35
- term.search_find_next if @regex
36
- end
37
-
38
- @entry.signal_connect("previous-match") do |entry|
39
- term.search_find_previous if @regex
40
- end
41
-
42
- @entry.signal_connect "search-changed" do |entry|
43
- pattern = entry.buffer.text
44
- if pattern != ""
45
- @regex = GLib::Regex.new(pattern)
46
- term.search_set_gregex(@regex, @regex.match_flags)
47
- term.search_find_next
48
- end
49
- end
50
- end
51
- end
@@ -1,397 +0,0 @@
1
- # Copyright 2017 Cedric LE MOIGNE, cedlemo@gmx.com
2
- # This file is part of Topinambour.
3
- #
4
- # Topinambour is free software: you can redistribute it and/or modify
5
- # it under the terms of the GNU General Public License as published by
6
- # the Free Software Foundation, either version 3 of the License, or
7
- # any later version.
8
- #
9
- # Topinambour is distributed in the hope that it will be useful,
10
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- # GNU General Public License for more details.
13
- #
14
- # You should have received a copy of the GNU General Public License
15
- # along with Topinambour. If not, see <http://www.gnu.org/licenses/>.
16
- class TopinambourTermChooser < Gtk::ScrolledWindow
17
- def initialize(window)
18
- super(nil, nil)
19
- @window = window
20
- @notebook = @window.notebook
21
- @notebook.generate_tab_preview
22
- initialize_list_box
23
- initialize_hidden_list_box
24
- initialize_main_box
25
- configure_window
26
- end
27
-
28
- private
29
-
30
- def configure_window
31
- set_halign(:end)
32
- set_valign(:center)
33
- set_policy(:never, :automatic)
34
- set_name("terminal_chooser")
35
- add(@box)
36
- set_size_request(-1, @notebook.current.term.allocation.to_a[3] - 8)
37
- end
38
-
39
- def initialize_main_box
40
- @box = Gtk::Box.new(:vertical, 4)
41
- @box.name = "topinambour-overview-box"
42
- @box.pack_start(main_title, :expand => false, :fill => true, :padding => 6)
43
- @box.pack_start(@listbox, :expand => true, :fill => true, :padding => 12)
44
- @box.pack_start(box_title("Hidden terminals"),
45
- :expand => false, :fill => true, :padding => 6)
46
- @box.pack_start(@listbox_hidden, :expand => true, :fill => true,
47
- :padding => 12)
48
- end
49
-
50
- def main_title
51
- hbox = Gtk::Box.new(:horizontal, 6)
52
- hbox.pack_start(box_title("Terminals"),
53
- :expand => true, :fill => true, :padding => 6)
54
- hbox.pack_start(box_close_button,
55
- :expand => false, :fill => false, :padding => 6)
56
- hbox
57
- end
58
-
59
- def box_title(label)
60
- title = Gtk::Label.new("> #{label} :")
61
- title.halign = :start
62
- title
63
- end
64
-
65
- def box_close_button
66
- button = Gtk::Button.new(:icon_name => "window-close-symbolic",
67
- :size => :button)
68
- button.relief = :none
69
- button.signal_connect("clicked") { @window.exit_overlay_mode }
70
- button
71
- end
72
-
73
- def initialize_list_box
74
- @listbox = Gtk::ListBox.new
75
- @listbox.margin = 12
76
- @listbox.selection_mode = :single
77
- fill_list_box
78
- end
79
-
80
- def initialize_hidden_list_box
81
- @listbox_hidden = Gtk::ListBox.new
82
- @listbox_hidden.placeholder = Gtk::Label.new("Hidden terminals")
83
- @listbox_hidden.margin = 12
84
- @listbox_hidden.show_all
85
- @listbox_hidden.selection_mode = :single
86
- fill_hidden_list_box
87
- end
88
-
89
- def fill_list_box
90
- @listbox.signal_connect "row-selected" do |_list, row|
91
- @notebook.current_page = row.nil? ? @notebook.children.size : row.index
92
- end
93
-
94
- @notebook.children.each_with_index do |child, i|
95
- row = generate_list_box_row(child.term, i)
96
- @listbox.insert(row, i)
97
- row.close_button.signal_connect "clicked" do |widget|
98
- close_button_action(widget)
99
- end
100
- end
101
- current_row = @listbox.get_row_at_index(@notebook.current_page)
102
- @listbox.select_row(current_row)
103
- current_row.grab_focus
104
- end
105
-
106
- def fill_hidden_list_box
107
- @notebook.hidden.each_with_index do |child, i|
108
- row = generate_hidden_list_box_row(child.term, i)
109
- @listbox_hidden.insert(row, i)
110
- row.close_button.signal_connect "clicked" do |widget|
111
- close_button_action(widget)
112
- end
113
- end
114
- end
115
-
116
- def close_button_action(button)
117
- row = button.parent.parent
118
- listbox = row.parent
119
- if listbox == @listbox
120
- tab = @notebook.get_nth_page(row.index)
121
- @notebook.n_pages == 1 ? @window.quit_gracefully : @notebook.remove(tab)
122
- row.destroy
123
- update_tabs_num_labels
124
- elsif listbox == @listbox_hidden
125
- @notebook.hidden.delete_at(row.index)
126
- row.destroy
127
- update_tabs_num_labels
128
- end
129
- end
130
-
131
- def generate_list_box_row(term, index)
132
- list_box_row = ChooserListRow.new(term, index, @notebook)
133
- generate_hide_button(list_box_row)
134
- end
135
-
136
- def generate_hidden_list_box_row(term, index)
137
- list_box_row = ChooserListRow.new(term, index, @notebook)
138
- generate_show_button(list_box_row)
139
- end
140
-
141
- def generate_show_button(list_box_row)
142
- list_box_row.generate_new_action_button("Show")
143
- list_box_row.action_button.signal_connect "clicked" do
144
- tab_num = list_box_row.index
145
- @window.notebook.unhide(tab_num)
146
- list_box_row_bkp = generate_hide_button(list_box_row)
147
- @listbox_hidden.remove(list_box_row)
148
- @listbox.insert(list_box_row_bkp, -1)
149
- update_tabs_num_labels
150
- end
151
- list_box_row
152
- end
153
-
154
- def generate_hide_button(list_box_row)
155
- list_box_row.generate_new_action_button("Hide")
156
- list_box_row.action_button.signal_connect "clicked" do
157
- num = list_box_row.index
158
- @notebook.n_pages == 1 ? @window.quit_gracefully : @notebook.hide(num)
159
- list_box_row_bkp = generate_show_button(list_box_row)
160
- @listbox.remove(list_box_row)
161
- @listbox_hidden.insert(list_box_row_bkp, -1)
162
- update_tabs_num_labels
163
- end
164
- list_box_row
165
- end
166
-
167
- def update_tabs_num_labels
168
- @listbox.children.each_with_index do |row, i|
169
- hbox = row.children[0]
170
- label = hbox.children[0]
171
- label.text = "tab. #{i + 1}"
172
- end
173
- update_hidden_tabs_num_labels
174
- end
175
-
176
- def update_hidden_tabs_num_labels
177
- @listbox_hidden.children.each_with_index do |row, i|
178
- hbox = row.children[0]
179
- label = hbox.children[0]
180
- label.text = "tab. #{i + 1}"
181
- end
182
- end
183
- end
184
-
185
- class ChooserListRow < Gtk::ListBoxRow
186
- attr_reader :close_button
187
- def initialize(term, index, notebook)
188
- super()
189
- @notebook = notebook
190
- @hbox = Gtk::Box.new(:horizontal, 6)
191
- fill_hbox_list_box_row(term, index)
192
- generate_action_button
193
- add(@hbox)
194
- end
195
-
196
- def action_button
197
- @hbox.children[4]
198
- end
199
-
200
- def generate_new_action_button(label)
201
- button = Gtk::Button.new(:label => label)
202
- button.valign = :center
203
- button.vexpand = false
204
- @hbox.remove(action_button)
205
- @hbox.pack_start(button,
206
- :expand => false, :fill => false, :padding => 6)
207
- show_all
208
- end
209
-
210
- private
211
-
212
- def fill_hbox_list_box_row(term, index)
213
- label = leaning_label(index)
214
- @hbox.pack_start(label, :expand => false, :fill => false, :padding => 6)
215
- @prev_button = generate_preview_button(term)
216
- add_drag_and_drop_functionalities
217
- @hbox.pack_start(@prev_button, :expand => false, :fill => false, :padding => 6)
218
- label = EditableLabel.new(term)
219
- @hbox.pack_start(label, :expand => true, :fill => false, :padding => 6)
220
- generate_close_button
221
- @hbox.pack_start(@close_button, :expand => false, :fill => false, :padding => 6)
222
- @hbox
223
- end
224
-
225
- def leaning_label(index)
226
- label = Gtk::Label.new("tab. #{index + 1}")
227
- label.angle = 45
228
- label
229
- end
230
-
231
- def generate_preview_button(child)
232
- button = Gtk::Button.new
233
- button.image = generate_preview_image(child.preview)
234
- button.signal_connect("clicked") do
235
- @notebook.current_page = index if parent.class == Gtk::ListBox
236
- end
237
- button
238
- end
239
-
240
- def generate_preview_image(pixbuf)
241
- # scaled_pix = pixbuf.scale(150, 75, :bilinear)
242
- scaled_pix = pixbuf.scale(200, 100, :bilinear)
243
- img = Gtk::Image.new(:pixbuf => scaled_pix)
244
- img.show
245
- img
246
- end
247
-
248
- def add_drag_and_drop_functionalities
249
- add_dnd_source(@prev_button)
250
- add_dnd_destination(@prev_button)
251
- end
252
-
253
- def add_dnd_source(button)
254
- button.drag_source_set(Gdk::ModifierType::BUTTON1_MASK |
255
- Gdk::ModifierType::BUTTON2_MASK,
256
- [["drag_term", Gtk::TargetFlags::SAME_APP, 12_345]],
257
- Gdk::DragAction::COPY |
258
- Gdk::DragAction::MOVE)
259
- # Drag source signals
260
- # drag-begin User starts a drag Set-up drag icon
261
- # drag-data-get When drag data is requested by the destination Transfer
262
- # drag data from source to destination
263
- # drag-data-delete When a drag with the action Gdk.DragAction.MOVE is
264
- # completed Delete data from the source to complete the "move"
265
- # drag-end When the drag is complete Undo anything done in drag-begin
266
-
267
- button.signal_connect "drag-begin" do |widget|
268
- widget.drag_source_set_icon_pixbuf(widget.image.pixbuf)
269
- end
270
-
271
- button.signal_connect("drag-data-get") do |widget, _, selection_data, _, _|
272
- index = widget.parent.parent.index
273
- selection_data.set(Gdk::Selection::TYPE_INTEGER, index.to_s)
274
- end
275
- # button.signal_connect "drag-data-delete" do
276
- # puts "drag data delete for #{inex}"
277
- # end
278
- # button.signal_connect "drag-end" do
279
- # puts "drag end for #{index}"
280
- # end
281
- end
282
-
283
- def add_dnd_destination(button)
284
- button.drag_dest_set(Gtk::DestDefaults::MOTION |
285
- Gtk::DestDefaults::HIGHLIGHT,
286
- [["drag_term", :same_app, 12_345]],
287
- Gdk::DragAction::COPY |
288
- Gdk::DragAction::MOVE)
289
-
290
- # Drag destination signals
291
- # drag-motion Drag icon moves over a drop area Allow only certain areas to
292
- # be dropped onto drag-drop Icon is dropped onto a drag area Allow only
293
- # certain areas to be dropped onto drag-data-received When drag data is
294
- # received by the destination Transfer drag data from source to destination
295
- # button.signal_connect "drag-motion" do
296
- # puts "drag motion for #{index}"
297
- # end
298
- button.signal_connect("drag-drop") do |widget, context, _x, _y, time|
299
- widget.drag_get_data(context, context.targets[0], time)
300
- end
301
-
302
- button.signal_connect("drag-data-received") do |widget, context, _x, _y, selection_data|
303
- index = widget.parent.parent.index
304
- index_of_dragged_object = index
305
- context.targets.each do |target|
306
- next unless target.name == "drag_term" ||
307
- selection_data.type == :type_integer
308
- data_len = selection_data.data.size
309
- index_of_dragged_object = selection_data.data.pack("C#{data_len}").to_i
310
- end
311
- if index_of_dragged_object != index
312
- drag_image_and_reorder_terms(index_of_dragged_object, index)
313
- end
314
- end
315
- end
316
-
317
- def drag_image_and_reorder_terms(src_index, dest_index)
318
- dragged = @notebook.get_nth_page(src_index)
319
- @notebook.reorder_child(dragged, dest_index)
320
- @notebook.children.each_with_index do |child, i|
321
- list_box_row = parent.get_row_at_index(i)
322
- row_h_box = list_box_row.children[0]
323
- row_h_box.children[1].image = generate_preview_image(child.term.preview)
324
- row_h_box.children[2].text = child.term.terminal_title
325
- end
326
- end
327
-
328
- def generate_close_button
329
- @close_button = Gtk::Button.new(:icon_name => "window-close-symbolic",
330
- :size => :button)
331
- @close_button.relief = :none
332
- end
333
-
334
- def generate_action_button
335
- action_button = Gtk::Button.new(:label => "")
336
- action_button.valign = :center
337
- action_button.vexpand = false
338
- @hbox.pack_start(action_button,
339
- :expand => false, :fill => false, :padding => 6)
340
- end
341
- end
342
-
343
- class EditableLabel < Gtk::Label
344
- def initialize(term)
345
- super(term.terminal_title)
346
- set_halign(:start)
347
- set_selectable(true)
348
- signal_connect "button-release-event" do |w, e|
349
- generate_label_popup(w, e, term)
350
- end
351
- label
352
- end
353
-
354
- def generate_label_popup(label, event, term)
355
- initialize_entry_popup(label)
356
- @popup = Gtk::Popover.new
357
- add_label_popup_entry_activate_signal(label, term)
358
- add_label_popup_entry_icon_release(label, term)
359
- @popup.add(@entry)
360
- set_popup_position(label, event)
361
- end
362
-
363
- def initialize_entry_popup(label)
364
- @entry = Gtk::Entry.new
365
- @entry.max_width_chars = 50
366
- @entry.buffer.text = label.text
367
- @entry.set_icon_from_icon_name(:secondary, "edit-clear-symbolic")
368
- end
369
-
370
- def add_label_popup_entry_icon_release(label, term)
371
- @entry.signal_connect "icon-release" do |widget, position|
372
- if position == :secondary
373
- term.custom_title = nil
374
- label.text = term.window_title
375
- term.toplevel.current_label.text = label.text
376
- widget.buffer.text = label.text
377
- end
378
- end
379
- end
380
-
381
- def add_label_popup_entry_activate_signal(label, term)
382
- @entry.signal_connect "activate" do |widget|
383
- label.text = widget.buffer.text
384
- term.custom_title = widget.buffer.text
385
- @popup.destroy
386
- end
387
- end
388
-
389
- def set_popup_position(label, event)
390
- x, y = event.window.coords_to_parent(event.x, event.y)
391
- rect = Gdk::Rectangle.new(x - label.allocation.x, y - label.allocation.y,
392
- 1, 1)
393
- @popup.pointing_to = rect
394
- @popup.relative_to = label
395
- @popup.show_all
396
- end
397
- end