VimMate 0.6.2
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/CHANGELOG +53 -0
- data/COPYING +20 -0
- data/README +198 -0
- data/Rakefile +72 -0
- data/TODO +9 -0
- data/bin/vimmate +179 -0
- data/lib/vimmatelib/config.rb +124 -0
- data/lib/vimmatelib/dummy_window.rb +39 -0
- data/lib/vimmatelib/file.png +0 -0
- data/lib/vimmatelib/file_green.png +0 -0
- data/lib/vimmatelib/file_orange.png +0 -0
- data/lib/vimmatelib/file_red.png +0 -0
- data/lib/vimmatelib/files.rb +230 -0
- data/lib/vimmatelib/files_menu.rb +325 -0
- data/lib/vimmatelib/files_window.rb +395 -0
- data/lib/vimmatelib/folder.png +0 -0
- data/lib/vimmatelib/folder_green.png +0 -0
- data/lib/vimmatelib/folder_orange.png +0 -0
- data/lib/vimmatelib/folder_red.png +0 -0
- data/lib/vimmatelib/icons.rb +104 -0
- data/lib/vimmatelib/main_window.rb +59 -0
- data/lib/vimmatelib/nice_singleton.rb +53 -0
- data/lib/vimmatelib/requirer.rb +68 -0
- data/lib/vimmatelib/search_window.rb +220 -0
- data/lib/vimmatelib/subversion.rb +157 -0
- data/lib/vimmatelib/terminals_window.rb +115 -0
- data/lib/vimmatelib/version.rb +29 -0
- data/lib/vimmatelib/vim_window.rb +84 -0
- data/lib/vimmatelib/vimmate16.png +0 -0
- data/lib/vimmatelib/vimmate32.png +0 -0
- data/lib/vimmatelib/vimmate48.png +0 -0
- data/setup.rb +1586 -0
- metadata +77 -0
@@ -0,0 +1,395 @@
|
|
1
|
+
=begin
|
2
|
+
= VimMate: Vim graphical add-on
|
3
|
+
Copyright (c) 2006 Guillaume Benny
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
9
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
10
|
+
so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
=end
|
23
|
+
|
24
|
+
require 'gtk2'
|
25
|
+
require 'set'
|
26
|
+
require 'thread'
|
27
|
+
require 'vimmatelib/config'
|
28
|
+
require 'vimmatelib/files'
|
29
|
+
require 'vimmatelib/icons'
|
30
|
+
require 'vimmatelib/search_window'
|
31
|
+
|
32
|
+
module VimMate
|
33
|
+
|
34
|
+
# The window that contains the file tree
|
35
|
+
class FilesWindow
|
36
|
+
|
37
|
+
# Column for the file name
|
38
|
+
NAME = 0
|
39
|
+
# Column for the full path of the file
|
40
|
+
PATH = 1
|
41
|
+
# Column for the icon of the file
|
42
|
+
ICON = 2
|
43
|
+
# Column used to sort the files
|
44
|
+
SORT = 3
|
45
|
+
# Column used to store the type of row
|
46
|
+
TYPE = 4
|
47
|
+
# Column used to store the status of the file
|
48
|
+
STATUS = 5
|
49
|
+
# Type of row: file
|
50
|
+
TYPE_FILE = 0
|
51
|
+
# Type of row: directory
|
52
|
+
TYPE_DIRECTORY = 1
|
53
|
+
# Type of row: separator
|
54
|
+
TYPE_SEPARATOR = 2
|
55
|
+
|
56
|
+
# Create a FilesWindow
|
57
|
+
def initialize(exclude_file_list = [])
|
58
|
+
@open_signal = Set.new
|
59
|
+
@menu_signal = Set.new
|
60
|
+
@expander_signal = Set.new
|
61
|
+
|
62
|
+
@filter_string = ""
|
63
|
+
|
64
|
+
# Tree Store: Filename, Full path, Icon, Sort, Type, Status
|
65
|
+
@gtk_tree_store = Gtk::TreeStore.new(String,
|
66
|
+
String,
|
67
|
+
Gdk::Pixbuf,
|
68
|
+
String,
|
69
|
+
Fixnum,
|
70
|
+
String)
|
71
|
+
@gtk_tree_store.set_sort_column_id(SORT)
|
72
|
+
|
73
|
+
# Filtered Tree Store
|
74
|
+
@gtk_filtered_tree_model = Gtk::TreeModelFilter.new(@gtk_tree_store)
|
75
|
+
@gtk_filtered_tree_model.set_visible_func do |model, iter|
|
76
|
+
if @filter_string.nil? or @filter_string.empty?
|
77
|
+
true
|
78
|
+
elsif iter[TYPE] == TYPE_DIRECTORY or iter[TYPE] == TYPE_SEPARATOR
|
79
|
+
true
|
80
|
+
else
|
81
|
+
if not iter[NAME] or iter[NAME].index(@filter_string)
|
82
|
+
true
|
83
|
+
else
|
84
|
+
false
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Tree View
|
90
|
+
@gtk_tree_view = Gtk::TreeView.new(@gtk_filtered_tree_model)
|
91
|
+
@gtk_tree_view.selection.mode = Gtk::SELECTION_SINGLE
|
92
|
+
@gtk_tree_view.headers_visible = Config[:file_headers_visible]
|
93
|
+
@gtk_tree_view.hover_selection = Config[:file_hover_selection]
|
94
|
+
|
95
|
+
# Double-click, Enter, Space: Signal to open the file
|
96
|
+
@gtk_tree_view.signal_connect("row-activated") do |view, path, column|
|
97
|
+
path = @gtk_filtered_tree_model.get_iter(path)[PATH]
|
98
|
+
@open_signal.each do |signal|
|
99
|
+
signal.call(path,
|
100
|
+
Config[:files_default_open_in_tabs] ? :tab_open : :open)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Left-click: Select and Signal to open the menu
|
105
|
+
@gtk_tree_view.signal_connect("button_press_event") do |widget, event|
|
106
|
+
if event.kind_of? Gdk::EventButton and event.button == 3
|
107
|
+
path = @gtk_tree_view.get_path_at_pos(event.x, event.y)
|
108
|
+
@gtk_tree_view.selection.select_path(path[0]) if path
|
109
|
+
|
110
|
+
selected = @gtk_tree_view.selection.selected
|
111
|
+
if selected
|
112
|
+
@menu_signal.each do |signal|
|
113
|
+
signal.call(selected[PATH])
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Create a label to show the path of the file
|
120
|
+
gtk_label = Gtk::Label.new
|
121
|
+
gtk_label.ellipsize = Pango::Layout::EllipsizeMode::START
|
122
|
+
|
123
|
+
# When a selection is changed in the tree view, we change the label
|
124
|
+
# to show the path of the file
|
125
|
+
@gtk_tree_view.selection.signal_connect("changed") do
|
126
|
+
gtk_label.text = ""
|
127
|
+
next if (selected_row = @gtk_tree_view.selection.selected).nil?
|
128
|
+
gtk_label.text = File.join(File.dirname(selected_row[PATH]), selected_row[NAME])
|
129
|
+
end
|
130
|
+
|
131
|
+
# Same thing as Left-click, but with the keyboard
|
132
|
+
@gtk_tree_view.signal_connect("popup_menu") do
|
133
|
+
selected = @gtk_tree_view.selection.selected
|
134
|
+
if selected
|
135
|
+
@menu_signal.each do |signal|
|
136
|
+
signal.call(selected[PATH])
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Separator between directories
|
142
|
+
@gtk_tree_view.set_row_separator_func do |model, iter|
|
143
|
+
iter[TYPE] == TYPE_SEPARATOR
|
144
|
+
end
|
145
|
+
|
146
|
+
# Add the columns
|
147
|
+
column = Gtk::TreeViewColumn.new
|
148
|
+
column.title = "Files"
|
149
|
+
|
150
|
+
# Icon
|
151
|
+
icon_cell_renderer = Gtk::CellRendererPixbuf.new
|
152
|
+
column.pack_start(icon_cell_renderer, false)
|
153
|
+
column.set_attributes(icon_cell_renderer, :pixbuf => ICON)
|
154
|
+
|
155
|
+
# File name
|
156
|
+
text_cell_renderer = Gtk::CellRendererText.new
|
157
|
+
if Config[:files_use_ellipsis]
|
158
|
+
text_cell_renderer.ellipsize = Pango::Layout::EllipsizeMode::MIDDLE
|
159
|
+
end
|
160
|
+
column.pack_start(text_cell_renderer, true)
|
161
|
+
column.set_attributes(text_cell_renderer, :text => NAME)
|
162
|
+
|
163
|
+
# Status
|
164
|
+
text_cell_renderer2 = Gtk::CellRendererText.new
|
165
|
+
if Config[:files_use_ellipsis]
|
166
|
+
text_cell_renderer2.ellipsize = Pango::Layout::EllipsizeMode::END
|
167
|
+
end
|
168
|
+
column.pack_start(text_cell_renderer2, true)
|
169
|
+
column.set_attributes(text_cell_renderer2, :text => STATUS)
|
170
|
+
|
171
|
+
@gtk_tree_view.append_column(column)
|
172
|
+
|
173
|
+
# Put the tree view in a scroll window
|
174
|
+
@gtk_scrolled_window = Gtk::ScrolledWindow.new
|
175
|
+
@gtk_scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC,
|
176
|
+
Gtk::POLICY_AUTOMATIC)
|
177
|
+
@gtk_scrolled_window.add(@gtk_tree_view)
|
178
|
+
|
179
|
+
# Set the default size for the file list
|
180
|
+
@gtk_scrolled_window.set_size_request(Config[:files_opened_width], -1)
|
181
|
+
|
182
|
+
# Create a box to filter the list
|
183
|
+
gtk_filter_box = Gtk::HBox.new
|
184
|
+
gtk_filter_box.pack_start(gtk_filter_button = Gtk::ToggleButton.new("Filter"), false, false)
|
185
|
+
gtk_filter_box.pack_start(gtk_entry = Gtk::Entry.new, true, true)
|
186
|
+
changed_lambda = lambda do
|
187
|
+
if gtk_filter_button.active?
|
188
|
+
self.filter = gtk_entry.text
|
189
|
+
else
|
190
|
+
self.clear_filter
|
191
|
+
end
|
192
|
+
end
|
193
|
+
gtk_entry.signal_connect("changed", &changed_lambda)
|
194
|
+
gtk_filter_button.signal_connect("toggled", &changed_lambda)
|
195
|
+
gtk_filter_button.active = Config[:files_filter_active]
|
196
|
+
gtk_filter_box.spacing = 10
|
197
|
+
gtk_filter_box.border_width = 10
|
198
|
+
|
199
|
+
# Create the file tree
|
200
|
+
initialize_file_tree(exclude_file_list)
|
201
|
+
|
202
|
+
gtk_top_box = Gtk::VBox.new
|
203
|
+
gtk_top_box.pack_start(gtk_filter_box, false, false)
|
204
|
+
gtk_top_box.pack_start(@gtk_scrolled_window, true, true)
|
205
|
+
gtk_top_box.pack_start(gtk_label, false, false)
|
206
|
+
|
207
|
+
# Create the search file list if it's enabled
|
208
|
+
if Config[:files_use_search]
|
209
|
+
@gtk_paned_box = Gtk::VPaned.new
|
210
|
+
@gtk_paned_box.add(gtk_top_box)
|
211
|
+
@gtk_paned_box.add((search_window = SearchWindow.new(@file_tree)).gtk_window)
|
212
|
+
@gtk_paned_box.position = Config[:files_search_separator_position]
|
213
|
+
|
214
|
+
# Set the signals for the search window
|
215
|
+
search_window.add_open_signal do |path, kind|
|
216
|
+
@open_signal.each do |signal|
|
217
|
+
signal.call(path, kind)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
search_window.add_menu_signal do |path|
|
221
|
+
@menu_signal.each do |signal|
|
222
|
+
signal.call(path)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
@gtk_expander = Gtk::Expander.new("File list")
|
229
|
+
@gtk_expander.expanded = Config[:files_expanded]
|
230
|
+
if Config[:files_use_search]
|
231
|
+
@gtk_expander.add(@gtk_paned_box)
|
232
|
+
else
|
233
|
+
@gtk_expander.add(gtk_top_box)
|
234
|
+
end
|
235
|
+
@gtk_expander.signal_connect("notify::expanded") do
|
236
|
+
@expander_signal.each do |signal|
|
237
|
+
signal.call(@gtk_expander.expanded?)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
gtk_window.border_width = 5
|
242
|
+
|
243
|
+
# Launch a timer to refresh the file list
|
244
|
+
@file_tree_mutex = Mutex.new
|
245
|
+
Gtk.timeout_add(Config[:files_refresh_interval] * 1000) do
|
246
|
+
do_refresh
|
247
|
+
true
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
# Recursively add a path at the root of the tree
|
252
|
+
def add_path(path)
|
253
|
+
@file_tree_mutex.synchronize do
|
254
|
+
@file_tree.add_path(path)
|
255
|
+
end
|
256
|
+
self
|
257
|
+
end
|
258
|
+
|
259
|
+
# The "window" for this object
|
260
|
+
def gtk_window
|
261
|
+
@gtk_expander
|
262
|
+
end
|
263
|
+
|
264
|
+
# Refresh the file list
|
265
|
+
def refresh
|
266
|
+
do_refresh
|
267
|
+
self
|
268
|
+
end
|
269
|
+
|
270
|
+
# Get the filter: files must contain this string
|
271
|
+
def filter
|
272
|
+
@filter_string
|
273
|
+
end
|
274
|
+
|
275
|
+
# Set a filter: files must contain this string
|
276
|
+
def filter=(filter)
|
277
|
+
@filter_string = filter
|
278
|
+
@gtk_filtered_tree_model.refilter
|
279
|
+
end
|
280
|
+
|
281
|
+
# Clear the filter
|
282
|
+
def clear_filter
|
283
|
+
@filter_string = ""
|
284
|
+
@gtk_filtered_tree_model.refilter
|
285
|
+
filter
|
286
|
+
end
|
287
|
+
|
288
|
+
# Expand the first row of the file tree
|
289
|
+
def expand_first_row
|
290
|
+
@gtk_tree_view.collapse_all
|
291
|
+
@gtk_tree_view.expand_row(Gtk::TreePath.new("0"), false)
|
292
|
+
end
|
293
|
+
|
294
|
+
# Add a block that will be called when the user choose to open a file
|
295
|
+
# The block take two argument: the path to the file to open, and a
|
296
|
+
# symbol to indicate the kind: :open, :split_open, :tab_open
|
297
|
+
def add_open_signal(&block)
|
298
|
+
@open_signal << block
|
299
|
+
end
|
300
|
+
|
301
|
+
# Add a block that will be called when the user choose to open the
|
302
|
+
# menu. The block takes one argument: the path to the file to open.
|
303
|
+
def add_menu_signal(&block)
|
304
|
+
@menu_signal << block
|
305
|
+
end
|
306
|
+
|
307
|
+
# Add a block that will be called when the user choose to expand or
|
308
|
+
# close the expander. The block takes one argument: if the expander
|
309
|
+
# is opened or closed
|
310
|
+
def add_expander_signal(&block)
|
311
|
+
@expander_signal << block
|
312
|
+
end
|
313
|
+
|
314
|
+
private
|
315
|
+
|
316
|
+
# Lunch the refresh of the tree
|
317
|
+
def do_refresh
|
318
|
+
@file_tree_mutex.synchronize do
|
319
|
+
@file_tree.refresh
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
# Create the file tree
|
324
|
+
def initialize_file_tree(exclude_file_list)
|
325
|
+
@file_tree = ListedTree.new(exclude_file_list)
|
326
|
+
|
327
|
+
# Register to receive a signal when a file is added or removed
|
328
|
+
@file_tree.add_refresh_signal do |method, file|
|
329
|
+
case method
|
330
|
+
when :add
|
331
|
+
# A file is added. Find it's parent and add it there
|
332
|
+
if file.parent
|
333
|
+
@gtk_tree_store.each do |model,path,iter|
|
334
|
+
if iter[PATH] == file.parent.path
|
335
|
+
add_to_tree(file, iter)
|
336
|
+
break
|
337
|
+
end
|
338
|
+
end
|
339
|
+
else
|
340
|
+
add_to_tree(file)
|
341
|
+
end
|
342
|
+
when :remove
|
343
|
+
# A file is removed. Find it and remove it
|
344
|
+
to_remove = []
|
345
|
+
@gtk_tree_store.each do |model,path,iter|
|
346
|
+
if iter[PATH] == file.path
|
347
|
+
to_remove << Gtk::TreeRowReference.new(model, path)
|
348
|
+
if iter.next! and iter[TYPE] == TYPE_SEPARATOR
|
349
|
+
to_remove << Gtk::TreeRowReference.new(model, path.next!)
|
350
|
+
end
|
351
|
+
break
|
352
|
+
end
|
353
|
+
end
|
354
|
+
to_remove.each do |element|
|
355
|
+
@gtk_tree_store.remove(@gtk_tree_store.get_iter(element.path))
|
356
|
+
end
|
357
|
+
when :refresh
|
358
|
+
# Called when the status of the file has changed
|
359
|
+
@gtk_tree_store.each do |model,path,iter|
|
360
|
+
if iter[PATH] == file.path
|
361
|
+
iter[ICON] = file.icon
|
362
|
+
iter[STATUS] = file.status_text
|
363
|
+
break
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
@gtk_filtered_tree_model.refilter
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
# Add a file to the tree
|
372
|
+
def add_to_tree(file, parent = nil)
|
373
|
+
# If we need a separator and it's a directory, we add it
|
374
|
+
if Config[:file_directory_separator] and file.instance_of? ListedDirectory
|
375
|
+
new_row = @gtk_tree_store.append(parent)
|
376
|
+
new_row[TYPE] = TYPE_SEPARATOR
|
377
|
+
new_row[SORT] = "1-#{file.path}-2"
|
378
|
+
end
|
379
|
+
# Add the row for the file
|
380
|
+
new_row = @gtk_tree_store.append(parent)
|
381
|
+
new_row[NAME] = file.name
|
382
|
+
new_row[PATH] = file.path
|
383
|
+
new_row[ICON] = file.icon
|
384
|
+
new_row[STATUS] = file.status_text
|
385
|
+
if file.instance_of? ListedDirectory
|
386
|
+
new_row[SORT] = "1-#{file.path}-1"
|
387
|
+
new_row[TYPE] = TYPE_DIRECTORY
|
388
|
+
else
|
389
|
+
new_row[SORT] = "2-#{file.path}-1"
|
390
|
+
new_row[TYPE] = TYPE_FILE
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,104 @@
|
|
1
|
+
=begin
|
2
|
+
= VimMate: Vim graphical add-on
|
3
|
+
Copyright (c) 2006 Guillaume Benny
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
9
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
10
|
+
so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
=end
|
23
|
+
|
24
|
+
require 'vimmatelib/nice_singleton'
|
25
|
+
|
26
|
+
module VimMate
|
27
|
+
|
28
|
+
# Manages the icons that can be loaded from the disk
|
29
|
+
class Icons
|
30
|
+
include NiceSingleton
|
31
|
+
|
32
|
+
# The filenames for the icons of the windows
|
33
|
+
WINDOW_ICON_FILENAME = 'vimmate%d.png'.freeze
|
34
|
+
# The size for the icons of the windows
|
35
|
+
WINDOW_ICON_SIZES = [16, 32, 48].freeze
|
36
|
+
|
37
|
+
# Name of the icons to load. Will create methods named after
|
38
|
+
# the icon's name, with _icon: folder_icon for example.
|
39
|
+
ICONS_NAME = [:folder, :file].collect do |f|
|
40
|
+
["", :green, :orange, :red].collect do |c|
|
41
|
+
if c.to_s.empty?
|
42
|
+
f.to_sym
|
43
|
+
else
|
44
|
+
"#{f}_#{c}".to_sym
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end.flatten.freeze
|
48
|
+
|
49
|
+
# Create the Icons class. Cannot be called directly
|
50
|
+
def initialize
|
51
|
+
@gtk_window_icons = []
|
52
|
+
end
|
53
|
+
|
54
|
+
# Get an array of icons for the windows
|
55
|
+
def window_icons
|
56
|
+
# Load them
|
57
|
+
load_window_icons
|
58
|
+
@gtk_window_icons.freeze
|
59
|
+
# Once loaded, we only need a reader
|
60
|
+
self.class.send(:define_method, :window_icons) do
|
61
|
+
@gtk_window_icons
|
62
|
+
end
|
63
|
+
# Return the value
|
64
|
+
window_icons
|
65
|
+
end
|
66
|
+
|
67
|
+
# Define a method with _icon for each icon's name
|
68
|
+
ICONS_NAME.each do |method|
|
69
|
+
define_method("#{method}_icon") do
|
70
|
+
# Load the file
|
71
|
+
icon = nil
|
72
|
+
file = File.join(Config.lib_path, "#{method}.png")
|
73
|
+
begin
|
74
|
+
icon = Gdk::Pixbuf.new(file) if File.exist? file
|
75
|
+
rescue StandardError => e
|
76
|
+
$stderr.puts e.to_s
|
77
|
+
$stderr.puts "Problem loading #{method} icon #{file}"
|
78
|
+
end
|
79
|
+
icon.freeze
|
80
|
+
# Once loaded, we only need a reader
|
81
|
+
self.class.send(:define_method, "#{method}_icon") do
|
82
|
+
icon
|
83
|
+
end
|
84
|
+
icon
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
# Load the icons for the windows
|
91
|
+
def load_window_icons
|
92
|
+
WINDOW_ICON_SIZES.each do |size|
|
93
|
+
file = File.join(Config.lib_path, WINDOW_ICON_FILENAME % [size])
|
94
|
+
begin
|
95
|
+
@gtk_window_icons << Gdk::Pixbuf.new(file) if File.exist? file
|
96
|
+
rescue StandardError => e
|
97
|
+
$stderr.puts e.to_s
|
98
|
+
$stderr.puts "Problem loading window icon #{file}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|