vimmate 0.8.1
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/.autotest +10 -0
- data/CHANGELOG +108 -0
- data/COPYING +20 -0
- data/README +221 -0
- data/Rakefile +31 -0
- data/TODO +21 -0
- data/bin/vimmate +105 -0
- data/config/environment.rb +35 -0
- data/controllers/file_filter_controller.rb +101 -0
- data/controllers/file_popup_menu_controller.rb +40 -0
- data/controllers/vim_controller.rb +28 -0
- data/controllers/vim_mate_controller.rb +76 -0
- data/images/file.png +0 -0
- data/images/file_green.png +0 -0
- data/images/file_orange.png +0 -0
- data/images/file_red.png +0 -0
- data/images/folder.png +0 -0
- data/images/folder_green.png +0 -0
- data/images/folder_orange.png +0 -0
- data/images/folder_red.png +0 -0
- data/images/processing.png +0 -0
- data/images/svn_added.png +0 -0
- data/images/svn_conflict.png +0 -0
- data/images/svn_deleted.png +0 -0
- data/images/svn_locked.png +0 -0
- data/images/svn_modified.png +0 -0
- data/images/svn_normal.png +0 -0
- data/images/svn_readonly.png +0 -0
- data/images/vimmate16.png +0 -0
- data/images/vimmate32.png +0 -0
- data/images/vimmate48.png +0 -0
- data/lib/active_window/active_column.rb +218 -0
- data/lib/active_window/active_tree_store/columns.rb +88 -0
- data/lib/active_window/active_tree_store/extentions.rb +81 -0
- data/lib/active_window/active_tree_store/index.rb +53 -0
- data/lib/active_window/active_tree_store.rb +26 -0
- data/lib/active_window/application.rb +137 -0
- data/lib/active_window/controller.rb +58 -0
- data/lib/active_window/dot_file.rb +29 -0
- data/lib/active_window/filtered_active_tree_store.rb +113 -0
- data/lib/active_window/listed_item.rb +127 -0
- data/lib/active_window/signal.rb +46 -0
- data/lib/active_window.rb +8 -0
- data/lib/config_window.rb +90 -0
- data/lib/file_tree_store.rb +74 -0
- data/lib/filtered_file_tree_store.rb +34 -0
- data/lib/gtk_thread_helper.rb +73 -0
- data/lib/listed_directory.rb +45 -0
- data/lib/listed_file.rb +67 -0
- data/lib/try.rb +9 -0
- data/lib/vim/buffers.rb +18 -0
- data/lib/vim/integration.rb +38 -0
- data/lib/vim/netbeans.rb +154 -0
- data/lib/vim/source.vim +18 -0
- data/lib/vim_mate/config.rb +132 -0
- data/lib/vim_mate/dummy_window.rb +14 -0
- data/lib/vim_mate/files_menu.rb +110 -0
- data/lib/vim_mate/icons.rb +156 -0
- data/lib/vim_mate/nice_singleton.rb +53 -0
- data/lib/vim_mate/plugins/inotify/init.rb +4 -0
- data/lib/vim_mate/plugins/inotify/lib/INotify.rb +208 -0
- data/lib/vim_mate/plugins/inotify/lib/directory.rb +58 -0
- data/lib/vim_mate/plugins/subversion/init.rb +7 -0
- data/lib/vim_mate/plugins/subversion/lib/file.rb +59 -0
- data/lib/vim_mate/plugins/subversion/lib/menu.rb +96 -0
- data/lib/vim_mate/plugins/subversion/lib/subversion.rb +157 -0
- data/lib/vim_mate/plugins.rb +6 -0
- data/lib/vim_mate/requirer.rb +68 -0
- data/lib/vim_mate/search_window.rb +227 -0
- data/lib/vim_mate/tags_window.rb +167 -0
- data/lib/vim_mate/terminals_window.rb +163 -0
- data/lib/vim_mate/version.rb +29 -0
- data/lib/vim_mate/vim_widget.rb +143 -0
- data/spec/active_window/active_column_spec.rb +41 -0
- data/spec/active_window/active_tree_store_spec.rb +312 -0
- data/spec/active_window/controller_spec.rb +6 -0
- data/spec/lib/file_tree_store_spec.rb +40 -0
- data/spec/lib/listed_directory_spec.rb +26 -0
- data/spec/lib/listed_file_spec.rb +53 -0
- data/spec/nice_singleton_spec.rb +23 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +10 -0
- data/views/vim_mate.glade +500 -0
- data/vimmate.gemspec +138 -0
- metadata +146 -0
@@ -0,0 +1,137 @@
|
|
1
|
+
class ActiveWindow::Application
|
2
|
+
include ActiveSupport::Callbacks
|
3
|
+
define_callbacks :after_initialize
|
4
|
+
|
5
|
+
attr_accessor :controller, :database, :glade, :window
|
6
|
+
|
7
|
+
def widget(name)
|
8
|
+
glade[name]
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@glade = GladeXML.new(find_glade, nil, options[:title] || 'application' )
|
13
|
+
@window = widget(options[:main_window] || 'main_window')
|
14
|
+
@window.signal_connect("destroy") { Gtk.main_quit }
|
15
|
+
@dot_file_prefs = DotFile.read
|
16
|
+
@database = options[:database]
|
17
|
+
define_widget_readers
|
18
|
+
run_callbacks :after_initialize
|
19
|
+
end
|
20
|
+
|
21
|
+
def start
|
22
|
+
setup
|
23
|
+
window.show
|
24
|
+
run
|
25
|
+
end
|
26
|
+
|
27
|
+
def run
|
28
|
+
Gtk.main
|
29
|
+
end
|
30
|
+
|
31
|
+
def default_database
|
32
|
+
@dot_file_prefs[:db]
|
33
|
+
end
|
34
|
+
|
35
|
+
def save_default_database(hash)
|
36
|
+
@dot_file_prefs[:db] = hash
|
37
|
+
@dot_file_prefs.save
|
38
|
+
end
|
39
|
+
|
40
|
+
# creates the controllers, connects the signals
|
41
|
+
# calls 'setup' on each controller
|
42
|
+
def setup
|
43
|
+
@controller = {}
|
44
|
+
|
45
|
+
Module.constants.grep(/.Controller$/).each do |klass|
|
46
|
+
ctrl = Kernel.const_get(klass).instance
|
47
|
+
ctrl.application = self
|
48
|
+
ctrl.setup
|
49
|
+
name = klass.to_s.sub('Controller','').underscore.to_sym # eg MyFirstController -> :my_first
|
50
|
+
controller[name] = ctrl
|
51
|
+
end
|
52
|
+
|
53
|
+
glade.signal_autoconnect_full do |source, target, signal, handler, data|
|
54
|
+
# for example:
|
55
|
+
# source : instance of Gtk::ImageMenuItem
|
56
|
+
# target : nil
|
57
|
+
# signal : activate, clicked, pressed, etc.
|
58
|
+
# handler : window.close, which would call WindowController.close()
|
59
|
+
# data : nil
|
60
|
+
#puts [source, target, signal, handler, data].inspect
|
61
|
+
source.signal_connect(signal) { |widget,event| self.dispatch(handler, :source => source, :target => target, :signal => signal, :handler => handler, :data => data, :widget => widget, :event => event) }
|
62
|
+
#source.signal_connect(signal) { self.(handler, data) }
|
63
|
+
end
|
64
|
+
post_setup
|
65
|
+
end
|
66
|
+
|
67
|
+
# calls post_setup on each controller
|
68
|
+
def post_setup
|
69
|
+
controller.each do |name,ctrl|
|
70
|
+
ctrl.post_setup
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
## dispatch a signal to the correct controller
|
76
|
+
##
|
77
|
+
def dispatch(handler, event)
|
78
|
+
controller_name,action = handler.to_s.split('.')
|
79
|
+
unless controller_name and action
|
80
|
+
return(error "cannot parse handler '%s'" % handler)
|
81
|
+
end
|
82
|
+
|
83
|
+
name = controller_name.to_sym
|
84
|
+
ctrl = controller[name]
|
85
|
+
unless ctrl
|
86
|
+
puts controller.inspect
|
87
|
+
return(error "no controller '%s' defined" % controller_name.camelize)
|
88
|
+
end
|
89
|
+
|
90
|
+
unless ctrl.respond_to? action
|
91
|
+
return(error "controller '%s' does not have a method '%s'" % [ctrl.class, action])
|
92
|
+
end
|
93
|
+
|
94
|
+
method = ctrl.method(action)
|
95
|
+
#puts "calling %s.%s" % [controller_name.camelize, action]
|
96
|
+
if method.arity == 0
|
97
|
+
method.call
|
98
|
+
else
|
99
|
+
method.call(event)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def class_exists?(classname)
|
107
|
+
return (Kernel::const_get(classname) rescue NameError) != NameError
|
108
|
+
end
|
109
|
+
|
110
|
+
def error(msg)
|
111
|
+
puts msg
|
112
|
+
end
|
113
|
+
|
114
|
+
def find_glade
|
115
|
+
Dir.glob("#{views_directory}/*.glade") do |f|
|
116
|
+
return f
|
117
|
+
end
|
118
|
+
raise "could not find a .glade file in #{views_directory}"
|
119
|
+
end
|
120
|
+
|
121
|
+
def views_directory
|
122
|
+
File.join(APP_ROOT, 'views')
|
123
|
+
end
|
124
|
+
|
125
|
+
def define_widget_readers
|
126
|
+
glade.widget_names.each do |widget|
|
127
|
+
meth = widget.underscore
|
128
|
+
instance_eval <<-EOEVAL
|
129
|
+
@#{meth} = glade['#{widget}']
|
130
|
+
def #{meth}
|
131
|
+
@#{meth}
|
132
|
+
end
|
133
|
+
EOEVAL
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# require 'libglade2'
|
2
|
+
# require 'gtk2'
|
3
|
+
|
4
|
+
class ActiveWindow::Controller
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
attr_accessor :application
|
8
|
+
|
9
|
+
def app
|
10
|
+
application
|
11
|
+
end
|
12
|
+
|
13
|
+
def widget(name)
|
14
|
+
application.widget(name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def controller
|
18
|
+
application.controller
|
19
|
+
end
|
20
|
+
|
21
|
+
def window
|
22
|
+
application.window
|
23
|
+
end
|
24
|
+
|
25
|
+
def database
|
26
|
+
application.database
|
27
|
+
end
|
28
|
+
|
29
|
+
# called on startup
|
30
|
+
def setup
|
31
|
+
end
|
32
|
+
|
33
|
+
# called on startup, after setup has been called for all controllers
|
34
|
+
def post_setup
|
35
|
+
end
|
36
|
+
|
37
|
+
def pref_set(key,value)
|
38
|
+
Preference.delete_all ['pref = ?', key]
|
39
|
+
Preference.create(:pref => key, :value => value)
|
40
|
+
value
|
41
|
+
end
|
42
|
+
|
43
|
+
def pref_get(key)
|
44
|
+
pref = Preference.find_by_pref(key)
|
45
|
+
return pref.value if pref
|
46
|
+
return nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def pref_get_or_set(key,value)
|
50
|
+
pref_get(key) || pref_set(key,value)
|
51
|
+
end
|
52
|
+
|
53
|
+
def method_missing(name, *args, &block)
|
54
|
+
application.send name, *args, &block
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
A simple class for reading and writing settings information
|
4
|
+
to a dot file (~/.appname.yml)
|
5
|
+
|
6
|
+
=end
|
7
|
+
|
8
|
+
module ActiveWindow
|
9
|
+
class DotFile < ::Hash
|
10
|
+
def self.read(fname=nil)
|
11
|
+
fname ||= filename
|
12
|
+
unless File.exists? fname
|
13
|
+
new.save(fname)
|
14
|
+
end
|
15
|
+
YAML.load_file( fname )
|
16
|
+
end
|
17
|
+
|
18
|
+
def save(fname=nil)
|
19
|
+
fname ||= self.class.filename
|
20
|
+
File.open( fname, 'w+' ) do |out|
|
21
|
+
YAML.dump( self, out )
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.filename
|
26
|
+
File.join ENV['HOME'], ".#{PROGRAM_NAME}.yml"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
# This creates a TreeModel which supports filtering. Please give a block that "returns" boolean
|
3
|
+
#
|
4
|
+
# filtered_model = ActiveTreeStoreFilter.new model do |filter_string, model, path, iter|
|
5
|
+
# !iter[23].index(filter_string).nil?
|
6
|
+
# end
|
7
|
+
class FilteredActiveTreeStore < Gtk::TreeModelFilter
|
8
|
+
include TreeStoreExtentions
|
9
|
+
|
10
|
+
attr_reader :filter_string, :found_count
|
11
|
+
attr_reader :unfiltered_store
|
12
|
+
define_callbacks :before_filter_applied, :after_filter_applied
|
13
|
+
define_callbacks :before_clear_filter, :after_clear_filter
|
14
|
+
|
15
|
+
def self.inherited(child_class)
|
16
|
+
unfiltered_class_name = child_class.name.sub(/^Filtered/,'')
|
17
|
+
unfiltered_class = unfiltered_class_name.constantize
|
18
|
+
child_class.columns = unfiltered_class.columns
|
19
|
+
child_class.column_id = unfiltered_class.column_id
|
20
|
+
child_class.setup_column_id_constants
|
21
|
+
unfiltered_class.class_eval <<-EOCODE
|
22
|
+
def add_with_filter_visibility(file, *args)
|
23
|
+
iter = add_without_filter_visibility(file, *args)
|
24
|
+
filtered_model.set_visibility_for(iter)
|
25
|
+
filtered_model.refilter unless initial_add_in_progress?
|
26
|
+
iter
|
27
|
+
end
|
28
|
+
alias_method_chain :add, :filter_visibility
|
29
|
+
attr_accessor :filtered_model
|
30
|
+
EOCODE
|
31
|
+
rescue NameError => e
|
32
|
+
if e.message =~ /uninitialized constant #{unfiltered_class}/
|
33
|
+
raise "there is no class named #{unfiltered_class} to filter from"
|
34
|
+
else
|
35
|
+
raise
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize(child_model)
|
40
|
+
super(child_model)
|
41
|
+
setup_filter
|
42
|
+
end
|
43
|
+
|
44
|
+
def filter_string=(new_filter_string)
|
45
|
+
if new_filter_string.empty?
|
46
|
+
clear_filter
|
47
|
+
else
|
48
|
+
@filter_string = new_filter_string
|
49
|
+
apply_filter
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def clear_filter
|
54
|
+
run_callbacks :before_clear_filter
|
55
|
+
@filter_string = ''
|
56
|
+
@found_count = -1
|
57
|
+
refilter
|
58
|
+
run_callbacks :after_clear_filter
|
59
|
+
end
|
60
|
+
|
61
|
+
# implement this to oyur own needs
|
62
|
+
def iter_visible?(iter)
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
66
|
+
# Iterate over child model and set visible column according to #iter_visible?
|
67
|
+
def apply_filter
|
68
|
+
run_callbacks :before_filter_applied
|
69
|
+
@found_count = 0
|
70
|
+
child_model.each do |model,path,iter|
|
71
|
+
set_visibility_for(iter)
|
72
|
+
end
|
73
|
+
refilter
|
74
|
+
run_callbacks :after_filter_applied
|
75
|
+
end
|
76
|
+
|
77
|
+
def filtered?
|
78
|
+
!filter_string.blank?
|
79
|
+
end
|
80
|
+
alias_method :filter, :filter_string
|
81
|
+
alias_method :filter=, :filter_string=
|
82
|
+
alias_method :filtering?, :filtered?
|
83
|
+
|
84
|
+
def set_visibility_for(iter)
|
85
|
+
visid = self.class.column_id[:visible]
|
86
|
+
unless filtering?
|
87
|
+
iter[ visid ] = true
|
88
|
+
else
|
89
|
+
if iter_visible?(iter) # iter matches - mark it and all parents as visible
|
90
|
+
@found_count += 1
|
91
|
+
iter[ visid ] = true
|
92
|
+
i = iter
|
93
|
+
while i = i.parent
|
94
|
+
i[ visid ] = true
|
95
|
+
end
|
96
|
+
else
|
97
|
+
iter[ visid ] = false
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def setup_filter
|
105
|
+
set_visible_func do |model, iter|
|
106
|
+
!filtered? || iter[ self.class.column_id[:visible] ]
|
107
|
+
end
|
108
|
+
child_model.filtered_model = self
|
109
|
+
clear_filter
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
# The ListItem is created on the fly
|
3
|
+
# * to oo-abstract methods to its TreeIter
|
4
|
+
# * for iteration in TreeController
|
5
|
+
# * as object in ActiveTreeStore
|
6
|
+
class ListedItem
|
7
|
+
|
8
|
+
def initialize(opts = {})
|
9
|
+
@traversed = false
|
10
|
+
self
|
11
|
+
end
|
12
|
+
|
13
|
+
def sort
|
14
|
+
"item-#{iter}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def icon_name
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def icon
|
22
|
+
VimMate::Icons.by_name icon_name
|
23
|
+
end
|
24
|
+
|
25
|
+
# New by Gtk::TreeRowReference
|
26
|
+
def self.new_by_reference(reference)
|
27
|
+
new(:iter => reference.iter)
|
28
|
+
end
|
29
|
+
|
30
|
+
# New by Gtk::TreeIter
|
31
|
+
def self.new_by_iter(iter)
|
32
|
+
new(:iter => iter)
|
33
|
+
end
|
34
|
+
|
35
|
+
def message?
|
36
|
+
referenced_type == 'VimMate::Message'
|
37
|
+
end
|
38
|
+
|
39
|
+
def separator?
|
40
|
+
referenced_type == 'VimMate::Separator'
|
41
|
+
end
|
42
|
+
|
43
|
+
def file?
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
def directory?
|
48
|
+
false
|
49
|
+
end
|
50
|
+
|
51
|
+
def file_or_directory?
|
52
|
+
false
|
53
|
+
end
|
54
|
+
|
55
|
+
def show!
|
56
|
+
self.visible = true
|
57
|
+
# TODO hide seperator
|
58
|
+
#if directory? and Config[:file_directory_separator]
|
59
|
+
# if iter.next!
|
60
|
+
# tree.row_for_iter(iter).show!
|
61
|
+
# end
|
62
|
+
#end
|
63
|
+
end
|
64
|
+
def hide!
|
65
|
+
self.visible = false
|
66
|
+
# TODO hide seperator
|
67
|
+
#if directory? and Config[:file_directory_separator]
|
68
|
+
# if iter.next!
|
69
|
+
# tree.row_for_iter(iter).hide!
|
70
|
+
# end
|
71
|
+
#end
|
72
|
+
end
|
73
|
+
|
74
|
+
def visible?
|
75
|
+
visible
|
76
|
+
end
|
77
|
+
|
78
|
+
def matches?(str)
|
79
|
+
name.index(str)
|
80
|
+
end
|
81
|
+
|
82
|
+
def refresh
|
83
|
+
end
|
84
|
+
|
85
|
+
def reference
|
86
|
+
@reference ||= Gtk::TreeRowReference.new(tree.store, iter.path)
|
87
|
+
end
|
88
|
+
|
89
|
+
def reference=(new_ref)
|
90
|
+
if new_ref
|
91
|
+
@reference = new_ref
|
92
|
+
@iter = tree.store.get_iter(new_ref.path)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.build(attrs)
|
97
|
+
if full_path = attrs[:full_path]
|
98
|
+
if ::File.directory? full_path
|
99
|
+
'ListedDirectory'
|
100
|
+
elsif ::File.file? full_path
|
101
|
+
'ListedFile'
|
102
|
+
else
|
103
|
+
self
|
104
|
+
end
|
105
|
+
elsif iter = attrs[:iter] and !iter[REFERENCED_TYPE].nil?
|
106
|
+
iter[REFERENCED_TYPE]
|
107
|
+
else
|
108
|
+
self
|
109
|
+
end.constantize.new attrs
|
110
|
+
end
|
111
|
+
|
112
|
+
def to_s
|
113
|
+
"#{self.class} [#{iter.path}]"
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.modify_icon(scope, &block)
|
117
|
+
with = "icon_name_with_#{scope}"
|
118
|
+
without = "icon_name_without_#{scope}"
|
119
|
+
define_method with do
|
120
|
+
block.call(self)
|
121
|
+
end
|
122
|
+
alias_method without, :icon_name
|
123
|
+
alias_method :icon_name, with
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
class Signal
|
3
|
+
class UnknownSignalError < StandardError ; end
|
4
|
+
@@signals = {}
|
5
|
+
|
6
|
+
def self.on(name, &block)
|
7
|
+
@@signals[name] ||= []
|
8
|
+
@@signals[name] << block
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.emit(name, *args)
|
12
|
+
if @@signals[name].is_a?(Array)
|
13
|
+
@@signals[name].each do |block|
|
14
|
+
block.call(*args)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.signals
|
20
|
+
@@signals
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.define name
|
24
|
+
class_eval <<-EOCODE
|
25
|
+
def self.emit_#{name}(*args)
|
26
|
+
self.emit(:#{name},*args)
|
27
|
+
end
|
28
|
+
def self.on_#{name}(&block)
|
29
|
+
self.on(:#{name}, &block)
|
30
|
+
end
|
31
|
+
EOCODE
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.method_missing(meth,*args,&block)
|
35
|
+
case meth.to_s
|
36
|
+
when /^emit_(.*)$/
|
37
|
+
raise UnknownSignalError, "cannot emit unknown signal '#{$1}'"
|
38
|
+
when /^on_(.*)$/
|
39
|
+
raise UnknownSignalError, "cannot connect to unknown signal '#{$1}'"
|
40
|
+
else
|
41
|
+
raise NoMethodError, "unknown method: #{meth}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
|
3
|
+
end
|
4
|
+
require_dependency 'active_window/signal'
|
5
|
+
require_dependency 'active_window/active_tree_store/columns'
|
6
|
+
require_dependency 'active_window/active_tree_store/index'
|
7
|
+
require_dependency 'active_window/active_tree_store/extentions'
|
8
|
+
require_dependency 'active_window/filtered_active_tree_store'
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module VimMate
|
2
|
+
class ConfigWindow
|
3
|
+
attr_reader :container
|
4
|
+
def initialize(main_window=nil)
|
5
|
+
@gtk_main_window = Gtk::Dialog.new("Configuration", main_window, Gtk::Dialog::MODAL,
|
6
|
+
[ Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_REJECT ],
|
7
|
+
[ Gtk::Stock::OK, Gtk::Dialog::RESPONSE_ACCEPT ]
|
8
|
+
)
|
9
|
+
gtk_window.set_default_size(400,300)
|
10
|
+
gtk_window.signal_connect('response') do |win,resp|
|
11
|
+
case resp
|
12
|
+
when Gtk::Dialog::RESPONSE_ACCEPT
|
13
|
+
save_settings
|
14
|
+
win.close
|
15
|
+
when Gtk::Dialog::RESPONSE_REJECT
|
16
|
+
win.close
|
17
|
+
when Gtk::Dialog::RESPONSE_NONE
|
18
|
+
puts "closing"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
@container = gtk_window.vbox
|
22
|
+
fill_container
|
23
|
+
gtk_window.show_all
|
24
|
+
end
|
25
|
+
# The "window" for this object
|
26
|
+
def gtk_window
|
27
|
+
@gtk_main_window
|
28
|
+
end
|
29
|
+
|
30
|
+
def fill_container
|
31
|
+
@fields = {}
|
32
|
+
Config::DEFAULT_CONFIG.keys.sort {|a,b| a.to_s <=> b.to_s}.each do |key|
|
33
|
+
val = Config[key]
|
34
|
+
box = Gtk::HBox.new(true,10)
|
35
|
+
label = Gtk::Label.new(key.to_s.humanize)
|
36
|
+
label.xalign = 1
|
37
|
+
box.pack_start label, true, true
|
38
|
+
|
39
|
+
field = field_for val
|
40
|
+
@fields[key] = field
|
41
|
+
box.pack_start field, true, false
|
42
|
+
container.pack_start box
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def save_settings
|
47
|
+
Config::DEFAULT_CONFIG.keys.each do |key|
|
48
|
+
if new_val = val_of(key)
|
49
|
+
Config.config[key] = new_val
|
50
|
+
end
|
51
|
+
end
|
52
|
+
Config.write_config
|
53
|
+
end
|
54
|
+
|
55
|
+
def val_of(key)
|
56
|
+
field = @fields[key]
|
57
|
+
case Config::DEFAULT_CONFIG[key]
|
58
|
+
when String
|
59
|
+
field.text
|
60
|
+
when Fixnum
|
61
|
+
field.value.to_i
|
62
|
+
when Float
|
63
|
+
field.value.to_f
|
64
|
+
when FalseClass, TrueClass
|
65
|
+
field.active?
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def field_for(val)
|
70
|
+
case val
|
71
|
+
when String
|
72
|
+
# TODO make "textarea" for more than 42 chars
|
73
|
+
e = Gtk::Entry.new
|
74
|
+
e.editable = true
|
75
|
+
e.text = val
|
76
|
+
e
|
77
|
+
when Fixnum, Float
|
78
|
+
Gtk::SpinButton.new(
|
79
|
+
Gtk::Adjustment.new(val,0,10000,1,10,1),
|
80
|
+
1,0)
|
81
|
+
when FalseClass, TrueClass
|
82
|
+
e = Gtk::ToggleButton.new
|
83
|
+
e.active = val
|
84
|
+
e
|
85
|
+
else
|
86
|
+
Gtk::Label.new(val.to_s)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
class FileTreeStore < ActiveWindow::ActiveTreeStore
|
2
|
+
column :full_path, String, :visible => false
|
3
|
+
column :status, String, :visible => false
|
4
|
+
column :sort, String, :visible => false
|
5
|
+
|
6
|
+
composite_column 'Files' do |col|
|
7
|
+
col.add column(:icon, Gdk::Pixbuf), false
|
8
|
+
col.add column(:name, String)
|
9
|
+
end
|
10
|
+
|
11
|
+
index_by :full_path
|
12
|
+
|
13
|
+
attr_reader :excludes
|
14
|
+
def initialize
|
15
|
+
super
|
16
|
+
@excludes ||= []
|
17
|
+
set_sort_column_id self.class.column_id[:sort]
|
18
|
+
ActiveWindow::Signal.on_file_modified { |path| refresh_path(path) }
|
19
|
+
ActiveWindow::Signal.on_file_created { |path| add_path(path) }
|
20
|
+
ActiveWindow::Signal.on_file_deleted { |path| remove_path(path) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_path(path, parent=nil)
|
24
|
+
unless excludes?(File.expand_path(path))
|
25
|
+
file = ListedFile.create(:full_path => path)
|
26
|
+
iter = add file, parent || find_by_full_path( File.dirname(path) )
|
27
|
+
if file.directory?
|
28
|
+
file.children_paths.each do |child|
|
29
|
+
add_path(child, iter)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
rescue ArgumentError => e
|
34
|
+
STDERR.puts e.message
|
35
|
+
end
|
36
|
+
|
37
|
+
def refresh_path(path)
|
38
|
+
if iter = find_by_full_path(path)
|
39
|
+
update_iter_from_object(iter, iter[OBJECT])
|
40
|
+
if iter[OBJECT].directory?
|
41
|
+
each do |iter|
|
42
|
+
if iter[FULL_PATH].start_with?(path)
|
43
|
+
refresh_path iter[FULL_PATH]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def remove_path(file_path)
|
51
|
+
if has_full_path?(file_path)
|
52
|
+
to_remove = []
|
53
|
+
each do |model,path,iter|
|
54
|
+
if iter[FULL_PATH].starts_with?(file_path)
|
55
|
+
to_remove << reference_for(iter)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
to_remove.each do |element|
|
59
|
+
i = get_iter(element.path)
|
60
|
+
remove(i) if i
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Path ends with a node name contained in the exclude list
|
66
|
+
def excludes?(path)
|
67
|
+
excludes.any? {|f| path[-(f.size+1)..-1] == "/#{f}" }
|
68
|
+
end
|
69
|
+
|
70
|
+
def exclude!(new_exclude)
|
71
|
+
excludes << new_exclude.chomp.strip
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|