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