topinambour 1.0.16 → 2.0.0

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