VimMate 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,124 @@
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 'yaml'
25
+ require 'vimmatelib/nice_singleton'
26
+
27
+ module VimMate
28
+
29
+ # Holds the configurations for VimMate. Also read and write this
30
+ # configuration so the user can change it.
31
+ class Config
32
+ include NiceSingleton
33
+
34
+ BASE_FILENAME = '.vimmaterc'
35
+ DEFAULT_CONFIG = {
36
+ :window_title => 'VimMate',
37
+ :window_width => 950,
38
+ :window_height => 600,
39
+ :layout_big_terminals => false,
40
+ :files_opened_width => 250,
41
+ :files_closed_width => 25,
42
+ :files_expanded => true,
43
+ :file_headers_visible => false,
44
+ :file_hover_selection => false,
45
+ :file_directory_separator => true,
46
+ :files_filter_active => true,
47
+ :files_refresh_interval => 10,
48
+ :files_default_open_in_tabs => true,
49
+ :files_use_ellipsis => true,
50
+ :files_use_search => true,
51
+ :files_search_ignore_case => true,
52
+ :files_search_separator_position => 400,
53
+ :terminals_enabled => true,
54
+ :terminals_height => 50,
55
+ :terminals_font => "10",
56
+ :terminals_foreground_color => "#000000",
57
+ :terminals_background_color => "#FFFFDD",
58
+ :terminals_audible_bell => false,
59
+ :terminals_visible_bell => false,
60
+ :terminals_autoexec => "",
61
+ :subversion_enabled => true,
62
+ }.freeze
63
+
64
+ # Create the Config class. Cannot be called directly
65
+ def initialize
66
+ # Set the full path to the configuration file. In the user's
67
+ # HOME or the current directory
68
+ if ENV['HOME']
69
+ self.class.const_set(:FILENAME, File.join(ENV['HOME'], BASE_FILENAME))
70
+ else
71
+ self.class.const_set(:FILENAME, BASE_FILENAME)
72
+ end
73
+ @config = DEFAULT_CONFIG.dup
74
+ end
75
+
76
+ # Access the configuration hash
77
+ def config
78
+ read_config
79
+ @config.freeze
80
+ # Once read, we only need a simple reader
81
+ self.class.send(:attr_reader, :config)
82
+ config
83
+ end
84
+
85
+ # Easy access to the configuration hash
86
+ def [](symbol)
87
+ config[symbol.to_sym]
88
+ end
89
+
90
+ # Get the lib path
91
+ def lib_path
92
+ File.dirname(File.expand_path(__FILE__))
93
+ end
94
+
95
+ private
96
+
97
+ # Read the configuration file
98
+ def read_config
99
+ # Write the default if it doesn't exist
100
+ unless File.exist? FILENAME
101
+ write_config
102
+ return
103
+ end
104
+ # Read the configuration file and merge it with the default
105
+ # so if the user doesn't specify an option, it's set to the default
106
+ @config.merge!(YAML.load_file(FILENAME))
107
+ write_config
108
+ rescue StandardError => e
109
+ $stderr.puts e.to_s
110
+ $stderr.puts "Problem reading config file #{FILENAME}, using default"
111
+ end
112
+
113
+ # Write the configuration file
114
+ def write_config
115
+ File.open(FILENAME, 'w') do |file|
116
+ YAML.dump(@config, file)
117
+ end
118
+ rescue StandardError => e
119
+ $stderr.puts e.to_s
120
+ $stderr.puts "Problem writing config file #{FILENAME}"
121
+ end
122
+ end
123
+ end
124
+
@@ -0,0 +1,39 @@
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
+
26
+ module VimMate
27
+
28
+ # Represents a dummy window used when a feature is missing
29
+ class DummyWindow
30
+
31
+ attr_reader :gtk_window
32
+
33
+ # Create a DummyWindow
34
+ def initialize
35
+ @gtk_window = Gtk::EventBox.new
36
+ end
37
+ end
38
+ end
39
+
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,230 @@
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 'set'
25
+ require 'vimmatelib/icons'
26
+ require 'vimmatelib/requirer'
27
+
28
+ module VimMate
29
+
30
+ # A file within the tree
31
+ class ListedFile
32
+ attr_reader :name, :path, :parent
33
+
34
+ # Create a ListedFile from a path and an optional parent. A block
35
+ # must be passed so it can be called to signal changes.
36
+ def initialize(path, parent = nil, &block)
37
+ @path = path
38
+ @name = File.basename(path)
39
+ @parent = parent
40
+ @tree_signal = block
41
+ @tree_signal.call(:add, self)
42
+ @last_status = nil
43
+ end
44
+
45
+ # Refresh the file. Doesn't do anything since it's the directory
46
+ # that does the job.
47
+ def refresh
48
+ self
49
+ end
50
+
51
+ # Returns the icon for this file
52
+ def icon
53
+ Icons.file_icon
54
+ end
55
+
56
+ # Returns the status text for this file
57
+ def status_text
58
+ ""
59
+ end
60
+
61
+ # If subversion can be required, change the definition of some functions
62
+ Requirer.require_if('vimmatelib/subversion') do
63
+ # Refresh the file. If the file status has changed, send a refresh
64
+ # signal
65
+ def refresh
66
+ status = Subversion.status(@path)
67
+ if @last_status != status
68
+ @last_status = status
69
+ @tree_signal.call(:refresh, self)
70
+ end
71
+ self
72
+ end
73
+
74
+ # Return the icon for this file depending on the file status
75
+ def icon
76
+ status = Subversion.status(@path)
77
+ if @last_status != status
78
+ @last_status = status
79
+ end
80
+ case status
81
+ when Subversion::UNVERSIONED, Subversion::EXTERNAL,
82
+ Subversion::IGNORED, Subversion::UNKNOWN
83
+ Icons.send("#{icon_type}_icon")
84
+ when Subversion::NONE, Subversion::NORMAL
85
+ Icons.send("#{icon_type}_green_icon")
86
+ when Subversion::ADDED, Subversion::DELETED,
87
+ Subversion::REPLACED, Subversion::MODIFIED
88
+ Icons.send("#{icon_type}_orange_icon")
89
+ when Subversion::MISSING, Subversion::MERGED,
90
+ Subversion::CONFLICTED, Subversion::OBSTRUCTED,
91
+ Subversion::INCOMPLETE
92
+ Icons.send("#{icon_type}_red_icon")
93
+ end
94
+ end
95
+
96
+ # Return the status text for this file depending on the file status
97
+ def status_text
98
+ Subversion.status_text(@path)
99
+ end
100
+ end
101
+
102
+ # The type of icon to use
103
+ def icon_type
104
+ :file
105
+ end
106
+ end
107
+
108
+ # A directory within the tree. Can contain files and other directories.
109
+ class ListedDirectory < ListedFile
110
+ include Enumerable
111
+
112
+ # Create a ListedDirectory from a path and an optional parent. A block
113
+ # must be passed so it can be called to signal changes.
114
+ def initialize(path, exclude_file_list, parent = nil, &block)
115
+ super(path, parent, &block)
116
+ @files = Set.new
117
+ @exclude_file_list = exclude_file_list
118
+ refresh
119
+ end
120
+
121
+ # Yield each files and directory within this directory
122
+ def each(&block)
123
+ @files.each(&block)
124
+ self
125
+ end
126
+
127
+ # Refresh the files from this directory. If it doesn't exist, the
128
+ # file is removed. If it didn't exist before, the file is added.
129
+ def refresh
130
+ super
131
+ # Find files to remove
132
+ files_to_remove = Set.new
133
+ all_paths = Set.new
134
+ each do |file|
135
+ file.refresh
136
+ if File.exist? file.path
137
+ all_paths << file.path
138
+ else
139
+ files_to_remove << file
140
+ @tree_signal.call(:remove, file)
141
+ end
142
+ end
143
+ @files -= files_to_remove
144
+
145
+ # Find files to add
146
+ begin
147
+ Dir.foreach(@path) do |file|
148
+ # Skip hidden files
149
+ next if file =~ /^\./
150
+ path = File.join(@path, file)
151
+ next if @exclude_file_list.any? {|f| path[-(f.size+1)..-1] == "/#{f}" }
152
+ # Skip files that we already have
153
+ next if all_paths.include? path
154
+ # Add the new file
155
+ @files << if File.directory? path
156
+ ListedDirectory.new(path, @exclude_file_list, self, &@tree_signal)
157
+ else
158
+ ListedFile.new(path, self, &@tree_signal)
159
+ end
160
+ end
161
+ rescue Errno::ENOENT
162
+ end
163
+ self
164
+ end
165
+
166
+ # The type of icon to use
167
+ def icon_type
168
+ :folder
169
+ end
170
+ end
171
+
172
+ # A tree of files and directory. Can signal added and removed files.
173
+ class ListedTree
174
+ include Enumerable
175
+
176
+ # Create a ListedTree which contains ListedFile and ListedDirectory
177
+ def initialize(exclude_file_list = [])
178
+ @paths = Set.new
179
+ @refresh_signal = Set.new
180
+ @signal_method = method(:signal)
181
+ @exclude_file_list = exclude_file_list
182
+ end
183
+
184
+ # Yield each files and directory at the root of the tree
185
+ def each(&block)
186
+ @paths.each(&block)
187
+ self
188
+ end
189
+
190
+ # Add a path: a file or a directory. If it's a directory, all files
191
+ # within this directory are also added
192
+ def add_path(path)
193
+ return unless File.exist? path
194
+ return if @exclude_file_list.any? {|f| path[-(f.size+1)..-1] == "/#{f}" }
195
+ @paths << if File.directory? path
196
+ ListedDirectory.new(path, @exclude_file_list, &@signal_method)
197
+ else
198
+ ListedFile.new(path, &@signal_method)
199
+ end
200
+ self
201
+ end
202
+
203
+ # Refresh the files from the tree. Inexistent files are removed and
204
+ # new files are added
205
+ def refresh
206
+ each do |path|
207
+ path.refresh
208
+ end
209
+ self
210
+ end
211
+
212
+ # Add a block that will be called when a file is added or removed.
213
+ # The block take 2 arguments: method and file:
214
+ # method: :add, :remove or :refresh
215
+ # file: the ListedFile or ListedDirectory that is affected
216
+ def add_refresh_signal(&block)
217
+ @refresh_signal << block
218
+ end
219
+
220
+ private
221
+
222
+ # Signal that a file has been added or removed.
223
+ def signal(method, file)
224
+ @refresh_signal.each do |block|
225
+ block.call(method, file)
226
+ end
227
+ end
228
+ end
229
+ end
230
+
@@ -0,0 +1,325 @@
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 'fileutils'
26
+ require 'set'
27
+ require 'vimmatelib/config'
28
+ require 'vimmatelib/requirer'
29
+
30
+ module VimMate
31
+
32
+ # The pop-up menu used in the file tree
33
+ class FilesMenu
34
+
35
+ # Create a FilesMenu
36
+ def initialize(parent_window)
37
+ @parent_window = parent_window
38
+ @open_signals = Set.new
39
+ @refresh_signals = Set.new
40
+
41
+ # The last path is the path of the file that was used when
42
+ # the menu was opened
43
+ @last_path = nil
44
+
45
+ # Build the menu items
46
+ @gtk_menu = Gtk::Menu.new
47
+
48
+ @gtk_menu.append(open = Gtk::ImageMenuItem.new(Gtk::Stock::OPEN))
49
+ open.signal_connect("activate") do
50
+ menu_open
51
+ end
52
+
53
+ @gtk_menu.append(split_open = Gtk::MenuItem.new("_Split Open"))
54
+ split_open.signal_connect("activate") do
55
+ menu_split_open
56
+ end
57
+
58
+ @gtk_menu.append(tab_open = Gtk::MenuItem.new("_Tab Open"))
59
+ tab_open.signal_connect("activate") do
60
+ menu_tab_open
61
+ end
62
+
63
+ @gtk_menu.append(Gtk::SeparatorMenuItem.new)
64
+
65
+ @gtk_menu.append(new = Gtk::ImageMenuItem.new(Gtk::Stock::NEW))
66
+ new.signal_connect("activate") do
67
+ menu_new
68
+ end
69
+
70
+ @gtk_menu.append(new_folder = Gtk::MenuItem.new("New _Folder"))
71
+ new_folder.signal_connect("activate") do
72
+ menu_new_folder
73
+ end
74
+
75
+ @gtk_menu.append(Gtk::SeparatorMenuItem.new)
76
+
77
+ @gtk_menu.append(rename = Gtk::MenuItem.new("R_ename"))
78
+ rename.signal_connect("activate") do
79
+ menu_rename
80
+ end
81
+
82
+ @gtk_menu.append(delete = Gtk::ImageMenuItem.new(Gtk::Stock::DELETE))
83
+ delete.signal_connect("activate") do
84
+ menu_delete
85
+ end
86
+
87
+ @gtk_menu.append(Gtk::SeparatorMenuItem.new)
88
+
89
+ Requirer.require_if('vimmatelib/subversion') do
90
+ svn_sub_menu = Gtk::Menu.new
91
+
92
+ svn_sub_menu.append(svn_add = Gtk::ImageMenuItem.new(Gtk::Stock::ADD))
93
+ svn_add.signal_connect("activate") do
94
+ menu_svn_add
95
+ end
96
+
97
+ svn_sub_menu.append(svn_rename = Gtk::MenuItem.new("R_ename"))
98
+ svn_rename.signal_connect("activate") do
99
+ menu_svn_rename
100
+ end
101
+
102
+ svn_sub_menu.append(svn_delete = Gtk::ImageMenuItem.new(Gtk::Stock::DELETE))
103
+ svn_delete.signal_connect("activate") do
104
+ menu_svn_delete
105
+ end
106
+
107
+ svn_sub_menu.append(svn_revert = Gtk::ImageMenuItem.new(Gtk::Stock::REVERT_TO_SAVED))
108
+ svn_revert.signal_connect("activate") do
109
+ menu_svn_revert
110
+ end
111
+
112
+ @gtk_menu.append(subversion = Gtk::MenuItem.new("S_ubversion"))
113
+ subversion.submenu = svn_sub_menu
114
+ end
115
+
116
+ @gtk_menu.append(refresh = Gtk::ImageMenuItem.new(Gtk::Stock::REFRESH))
117
+ refresh.signal_connect("activate") do
118
+ menu_refresh
119
+ end
120
+
121
+ @gtk_menu.show_all
122
+ end
123
+
124
+ # Open the menu. Specify a path to show where the menu was opened.
125
+ def open(path)
126
+ @last_path = path
127
+ @gtk_menu.popup(nil, nil, 0, 0)
128
+ end
129
+
130
+ # Add a block that will be called when the user choose to open a file
131
+ # The block take two argument: the path to the file to open, and a
132
+ # symbol to indicate the kind: :open, :split_open, :tab_open
133
+ def add_open_signal(&block)
134
+ @open_signals << block
135
+ end
136
+
137
+ # Add a block that will be called when the user choose to refresh the
138
+ # file tree. The block doesn't take an argument.
139
+ def add_refresh_signal(&block)
140
+ @refresh_signals << block
141
+ end
142
+
143
+ private
144
+
145
+ # Signals that a file must be opened
146
+ def menu_open
147
+ @open_signals.each do |signal|
148
+ signal.call(@last_path, :open)
149
+ end
150
+ end
151
+
152
+ def menu_split_open
153
+ @open_signals.each do |signal|
154
+ signal.call(@last_path, :split_open)
155
+ end
156
+ end
157
+
158
+ def menu_tab_open
159
+ @open_signals.each do |signal|
160
+ signal.call(@last_path, :tab_open)
161
+ end
162
+ end
163
+
164
+ # Open a dialog to enter a new file name to create
165
+ def menu_new
166
+ dialog = Gtk::FileChooserDialog.new("New file",
167
+ @parent_window.gtk_window,
168
+ Gtk::FileChooser::ACTION_SAVE,
169
+ nil,
170
+ [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
171
+ [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT])
172
+ dialog.set_icon_list(Icons.window_icons)
173
+ dialog.current_folder = if File.directory? @last_path
174
+ @last_path
175
+ else
176
+ File.dirname(@last_path)
177
+ end
178
+ if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
179
+ begin
180
+ FileUtils.touch(dialog.filename)
181
+ rescue
182
+ $stderr.puts "Cannot touch #{dialog.filename}"
183
+ end
184
+ end
185
+ dialog.destroy
186
+ menu_refresh
187
+ end
188
+
189
+ # Open a dialog to enter a new folder name to create
190
+ def menu_new_folder
191
+ dialog = Gtk::FileChooserDialog.new("New folder",
192
+ @parent_window.gtk_window,
193
+ Gtk::FileChooser::ACTION_CREATE_FOLDER,
194
+ nil,
195
+ [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
196
+ [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT])
197
+ dialog.set_icon_list(Icons.window_icons)
198
+ dialog.current_folder = if File.directory? @last_path
199
+ @last_path
200
+ else
201
+ File.dirname(@last_path)
202
+ end
203
+ dialog.run
204
+ dialog.destroy
205
+ menu_refresh
206
+ end
207
+
208
+ # Open a dialog to enter a new name for a file or directory
209
+ def menu_rename
210
+ dialog = Gtk::FileChooserDialog.new("Rename #{File.basename(@last_path)}",
211
+ @parent_window.gtk_window,
212
+ Gtk::FileChooser::ACTION_SAVE,
213
+ nil,
214
+ [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
215
+ [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT])
216
+ dialog.set_icon_list(Icons.window_icons)
217
+ dialog.current_folder = File.dirname(@last_path)
218
+ if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
219
+ begin
220
+ File.rename(@last_path, dialog.filename)
221
+ rescue SystemCallError
222
+ $stderr.puts "Cannot rename from #{@last_path} to #{dialog.filename}"
223
+ end
224
+ end
225
+ dialog.destroy
226
+ menu_refresh
227
+ end
228
+
229
+ # Open a dialog and ask the user if he really wants to delete the target
230
+ # file or directory. Note that for safety, directories can only be removed
231
+ # if they are empty.
232
+ def menu_delete
233
+ name = File.basename(@last_path)
234
+ dialog = Gtk::MessageDialog.new(@parent_window.gtk_window,
235
+ Gtk::MessageDialog::Flags::MODAL,
236
+ Gtk::MessageDialog::Type::QUESTION,
237
+ Gtk::MessageDialog::ButtonsType::YES_NO,
238
+ if File.directory? @last_path
239
+ "Delete directory #{name} ?"
240
+ else
241
+ "Delete file #{name} ?"
242
+ end)
243
+ dialog.set_icon_list(Icons.window_icons)
244
+ if dialog.run == Gtk::Dialog::RESPONSE_YES
245
+ begin
246
+ if File.directory? @last_path
247
+ FileUtils.rmdir(@last_path)
248
+ else
249
+ FileUtils.rm(@last_path)
250
+ end
251
+ rescue
252
+ $stderr.puts "Cannot remove #{@last_path}"
253
+ end
254
+ end
255
+ dialog.destroy
256
+ menu_refresh
257
+ end
258
+
259
+ # Only define the Subversion methods if subversion is available
260
+ Requirer.require_if('vimmatelib/subversion') do
261
+
262
+ # Add the selected file to subversion
263
+ def menu_svn_add
264
+ Subversion.add(@last_path)
265
+ menu_refresh
266
+ end
267
+
268
+ # Rename the selected file with subversion
269
+ def menu_svn_rename
270
+ dialog = Gtk::FileChooserDialog.new("Rename #{File.basename(@last_path)}",
271
+ @parent_window.gtk_window,
272
+ Gtk::FileChooser::ACTION_SAVE,
273
+ nil,
274
+ [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
275
+ [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT])
276
+ dialog.set_icon_list(Icons.window_icons)
277
+ dialog.current_folder = File.dirname(@last_path)
278
+ if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
279
+ Subversion.move(@last_path, dialog.filename)
280
+ end
281
+ dialog.destroy
282
+ menu_refresh
283
+ end
284
+
285
+ # Revert the selected file in subversion
286
+ def menu_svn_revert
287
+ dialog = Gtk::MessageDialog.new(@parent_window.gtk_window,
288
+ Gtk::MessageDialog::Flags::MODAL,
289
+ Gtk::MessageDialog::Type::QUESTION,
290
+ Gtk::MessageDialog::ButtonsType::YES_NO,
291
+ "Do a Subversion Revert on #{File.basename(@last_path)} ?")
292
+ dialog.set_icon_list(Icons.window_icons)
293
+ if dialog.run == Gtk::Dialog::RESPONSE_YES
294
+ Subversion.revert(@last_path)
295
+ end
296
+ dialog.destroy
297
+ menu_refresh
298
+ end
299
+
300
+ # Delete the selected file from subversion
301
+ def menu_svn_delete
302
+ dialog = Gtk::MessageDialog.new(@parent_window.gtk_window,
303
+ Gtk::MessageDialog::Flags::MODAL,
304
+ Gtk::MessageDialog::Type::QUESTION,
305
+ Gtk::MessageDialog::ButtonsType::YES_NO,
306
+ "Do a Subversion Delete on #{File.basename(@last_path)} ?")
307
+ dialog.set_icon_list(Icons.window_icons)
308
+ if dialog.run == Gtk::Dialog::RESPONSE_YES
309
+ Subversion.remove(@last_path)
310
+ end
311
+ dialog.destroy
312
+ menu_refresh
313
+ end
314
+ end
315
+
316
+ # Signals that the file tree must be refreshed
317
+ def menu_refresh
318
+ @refresh_signals.each do |signal|
319
+ signal.call
320
+ end
321
+ end
322
+
323
+ end
324
+ end
325
+