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,40 @@
|
|
1
|
+
class FilePopupMenuController < ActiveWindow::Controller
|
2
|
+
|
3
|
+
def setup
|
4
|
+
@last_path = File.expand_path '.'
|
5
|
+
end
|
6
|
+
|
7
|
+
# Open a dialog to enter a new file name to create
|
8
|
+
# TODO use path of selected file
|
9
|
+
# TODO make inline renaming (like TextMate)
|
10
|
+
def new_file(given)
|
11
|
+
dialog = Gtk::FileChooserDialog.new("New file",
|
12
|
+
window,
|
13
|
+
Gtk::FileChooser::ACTION_SAVE,
|
14
|
+
nil,
|
15
|
+
[Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL],
|
16
|
+
[Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_ACCEPT])
|
17
|
+
#dialog.set_icon_list(Icons.window_icons)
|
18
|
+
dialog.current_folder = if File.directory? @last_path
|
19
|
+
@last_path
|
20
|
+
else
|
21
|
+
File.dirname(@last_path)
|
22
|
+
end
|
23
|
+
if dialog.run == Gtk::Dialog::RESPONSE_ACCEPT
|
24
|
+
begin
|
25
|
+
FileUtils.touch(dialog.filename)
|
26
|
+
rescue
|
27
|
+
$stderr.puts "Cannot touch #{dialog.filename}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
dialog.destroy
|
31
|
+
end
|
32
|
+
def new_directory(given)
|
33
|
+
end
|
34
|
+
def rename_item(given)
|
35
|
+
end
|
36
|
+
def delete_item(given)
|
37
|
+
end
|
38
|
+
def refresh_item(given)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class VimController < ActiveWindow::Controller
|
2
|
+
attr_accessor :vim
|
3
|
+
|
4
|
+
def setup
|
5
|
+
@vim = VimMate::VimWidget.new
|
6
|
+
main_pane.pack2(vim.window, true, false)
|
7
|
+
end
|
8
|
+
|
9
|
+
def open_selected_file
|
10
|
+
open_selected_file_as
|
11
|
+
end
|
12
|
+
|
13
|
+
def open_selected_file_split
|
14
|
+
open_selected_file_as :split
|
15
|
+
end
|
16
|
+
|
17
|
+
def open_selected_file_tab
|
18
|
+
open_selected_file_as :tab
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def open_selected_file_as(mode = VimMate::Config[:files_default_open_in_tabs] ? :tab : :open)
|
23
|
+
if iter = file_tree_view.selection.selected
|
24
|
+
vim.open iter[ FileTreeStore.full_path_column ], mode
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
class VimMateController < ActiveWindow::Controller
|
2
|
+
|
3
|
+
attr_accessor :terminals_window, :tags_tree
|
4
|
+
|
5
|
+
def post_setup
|
6
|
+
window.set_default_size( VimMate::Config[:window_width],
|
7
|
+
VimMate::Config[:window_height])
|
8
|
+
window.set_icon_list(VimMate::Icons.window_icons)
|
9
|
+
|
10
|
+
|
11
|
+
# Double-click, Enter, Space: Signal to open the file
|
12
|
+
#file_tree.on_row_activated &method(:on_file_tree_row_activated)
|
13
|
+
|
14
|
+
#file_tree.on_right_click &method(:open_file_popup)
|
15
|
+
#file_tree.on_popup_menu &method(:open_file_popup)
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
#@tags_tree = VimMate::TagsWindow.new(@vim)
|
20
|
+
#tags_scroller.add @tags_tree.gtk_window
|
21
|
+
|
22
|
+
## Set the signals for the file menu
|
23
|
+
#menu.add_open_signal do |path, kind|
|
24
|
+
# vim.open(path, kind)
|
25
|
+
#end
|
26
|
+
#menu.add_refresh_signal do
|
27
|
+
# files.refresh
|
28
|
+
#end
|
29
|
+
end
|
30
|
+
|
31
|
+
def pressed_key(given)
|
32
|
+
return unless event = given[:event]
|
33
|
+
if event.state & Gdk::Window::ModifierType::CONTROL_MASK != 0
|
34
|
+
if event.state & Gdk::Window::ModifierType::SHIFT_MASK != 0
|
35
|
+
case event.keyval
|
36
|
+
# CTRL+SHIFT+S: Set focus to terminal (shell)
|
37
|
+
when Gdk::Keyval::GDK_S
|
38
|
+
terminals_window.focus_terminal if terminals_window
|
39
|
+
# CTRL+SHIFT+T: New terminal
|
40
|
+
when Gdk::Keyval::GDK_T
|
41
|
+
terminals_window.add_new_terminal if terminals_window
|
42
|
+
# CTRL+SHIFT+W: Close terminal
|
43
|
+
when Gdk::Keyval::GDK_W
|
44
|
+
terminals_window.delete_current_terminal if terminals_window
|
45
|
+
# CTRL+SHIFT+L: Set focus to file filter
|
46
|
+
when Gdk::Keyval::GDK_L
|
47
|
+
files_filter_term.has_focus = true
|
48
|
+
# CTRL+SHIFT+F: Set focus to file list
|
49
|
+
when Gdk::Keyval::GDK_F
|
50
|
+
file_tree_view.has_focus = true
|
51
|
+
# CTRL+SHIFT+S: Set focus to search file list
|
52
|
+
when Gdk::Keyval::GDK_E
|
53
|
+
files_window.focus_file_search if files_window
|
54
|
+
# CTRL+SHIFT+V: Set focus to Vim
|
55
|
+
when Gdk::Keyval::GDK_V
|
56
|
+
vim.focus!
|
57
|
+
end
|
58
|
+
else
|
59
|
+
#case event.keyval
|
60
|
+
## CTRL+PAGEDOWN: Next terminal
|
61
|
+
#when Gdk::Keyval::GDK_Page_Down
|
62
|
+
# terminals_window.next_terminal if terminals_window
|
63
|
+
# next true
|
64
|
+
## CTRL+PAGEDOWN: Previous terminal
|
65
|
+
#when Gdk::Keyval::GDK_Page_Up
|
66
|
+
# terminals_window.prev_terminal if terminals_window
|
67
|
+
# next true
|
68
|
+
#else
|
69
|
+
# next nil
|
70
|
+
#end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
data/images/file.png
ADDED
Binary file
|
Binary file
|
Binary file
|
data/images/file_red.png
ADDED
Binary file
|
data/images/folder.png
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,218 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
|
3
|
+
=begin
|
4
|
+
|
5
|
+
ActiveColumn is used to define columns for ActiveTreeStore
|
6
|
+
|
7
|
+
=end
|
8
|
+
|
9
|
+
class ActiveColumn
|
10
|
+
attr_accessor :id, :name
|
11
|
+
extend ActiveSupport::Memoizable
|
12
|
+
|
13
|
+
ClassesToSymbols = {
|
14
|
+
TrueClass => :boolean,
|
15
|
+
FalseClass => :boolean,
|
16
|
+
String => :string,
|
17
|
+
Time => :datetime,
|
18
|
+
Date => :datetime,
|
19
|
+
Fixnum => :integer,
|
20
|
+
Bignum => :integer,
|
21
|
+
Integer => :integer,
|
22
|
+
Float => :float,
|
23
|
+
Gdk::Pixbuf => :image
|
24
|
+
}
|
25
|
+
|
26
|
+
##
|
27
|
+
## column: ActiveRecord::ConnectionAdapters::MysqlColumn
|
28
|
+
##
|
29
|
+
def self.create(id, name, klass=:string, opts={})
|
30
|
+
klass = ClassesToSymbols[klass] if klass.is_a?(Class)
|
31
|
+
subclass = case klass # ignore warning this creates
|
32
|
+
when :string; ActiveTextColumn
|
33
|
+
when :datetime; ActiveDateColumn
|
34
|
+
when :integer; ActiveIntegerColumn
|
35
|
+
when :float; ActiveFloatColumn
|
36
|
+
when :boolean; ActiveToggleColumn
|
37
|
+
when :image; ActiveImageColumn
|
38
|
+
else; self
|
39
|
+
end
|
40
|
+
return subclass.new(id, name.to_s, opts)
|
41
|
+
end
|
42
|
+
|
43
|
+
def initialize(id, name, opts={})
|
44
|
+
self.id = id
|
45
|
+
self.name = name
|
46
|
+
@virtual = opts[:virtual] == true ? true : false
|
47
|
+
@visible = opts[:visible] == false ? false : true
|
48
|
+
#puts 'new column: %s %s' % [self.class, name]
|
49
|
+
end
|
50
|
+
|
51
|
+
def virtual?
|
52
|
+
@virtual
|
53
|
+
end
|
54
|
+
|
55
|
+
def hide!
|
56
|
+
@visible = false
|
57
|
+
end
|
58
|
+
|
59
|
+
def visible?
|
60
|
+
@visible
|
61
|
+
end
|
62
|
+
|
63
|
+
## return a Gtk::TreeViewColumn appropriate for showing this column
|
64
|
+
def view
|
65
|
+
raise "There is no way to show #{name} yet."
|
66
|
+
end
|
67
|
+
|
68
|
+
def renderer
|
69
|
+
raise "There is no way to render #{name} yet."
|
70
|
+
end
|
71
|
+
|
72
|
+
## return the class of the value held for this column in the model
|
73
|
+
def data_class
|
74
|
+
Object
|
75
|
+
end
|
76
|
+
|
77
|
+
## given an active record object, return the attribute
|
78
|
+
## value that corresponds to this column. the returned
|
79
|
+
## value must match the class returned in data_class.
|
80
|
+
## so, you might have to do some conversion.
|
81
|
+
def data_value(ar_object)
|
82
|
+
ar_object.send(self.name)
|
83
|
+
end
|
84
|
+
|
85
|
+
def view
|
86
|
+
r = renderer
|
87
|
+
column.pack_start(r, true)
|
88
|
+
column.add_attribute(r, attribute, self.id)
|
89
|
+
column
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
def column
|
94
|
+
@gtk_column ||= Gtk::TreeViewColumn.new(self.name)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
## ActiveTextColumn
|
100
|
+
##
|
101
|
+
## For columns with string values
|
102
|
+
##
|
103
|
+
class ActiveTextColumn < ActiveColumn
|
104
|
+
def data_class
|
105
|
+
String
|
106
|
+
end
|
107
|
+
def renderer
|
108
|
+
Gtk::CellRendererText.new
|
109
|
+
end
|
110
|
+
def attribute
|
111
|
+
:text
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class ActiveIntegerColumn < ActiveTextColumn
|
116
|
+
def data_class
|
117
|
+
Integer
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
##
|
122
|
+
## how to do?:
|
123
|
+
## renderer.signal_connect('toggled') do |cell, path|
|
124
|
+
## fixed_toggled(treeview.model, path)
|
125
|
+
## end
|
126
|
+
##
|
127
|
+
class ActiveToggleColumn < ActiveColumn
|
128
|
+
def data_class
|
129
|
+
TrueClass
|
130
|
+
end
|
131
|
+
def renderer
|
132
|
+
Gtk::CellRendererToggle.new
|
133
|
+
end
|
134
|
+
def attribute
|
135
|
+
:active
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
##
|
140
|
+
## TODO: configure the number of digits printed
|
141
|
+
##
|
142
|
+
class ActiveFloatColumn < ActiveColumn
|
143
|
+
def data_class
|
144
|
+
Float
|
145
|
+
end
|
146
|
+
def renderer
|
147
|
+
Gtk::CellRendererText.new
|
148
|
+
end
|
149
|
+
def attribute
|
150
|
+
:text
|
151
|
+
end
|
152
|
+
def view
|
153
|
+
super.set_cell_data_func(renderer) do |col, renderer, model, iter|
|
154
|
+
renderer.text = sprintf("%.2f", iter[self.id])
|
155
|
+
end
|
156
|
+
end
|
157
|
+
def data_value(ar_object)
|
158
|
+
super(ar_object) || 0
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
##
|
163
|
+
## TODO: configure the date format
|
164
|
+
##
|
165
|
+
class ActiveDateColumn < ActiveColumn
|
166
|
+
def data_class
|
167
|
+
Time
|
168
|
+
end
|
169
|
+
def renderer
|
170
|
+
Gtk::CellRendererText.new
|
171
|
+
end
|
172
|
+
def attribute
|
173
|
+
:text
|
174
|
+
end
|
175
|
+
def view
|
176
|
+
super.set_cell_data_func(renderer) do |col, renderer, model, iter|
|
177
|
+
renderer.text = sprintf("%x %X", iter[self.id])
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
class ActiveImageColumn < ActiveColumn
|
184
|
+
def data_class
|
185
|
+
Gdk::Pixbuf
|
186
|
+
end
|
187
|
+
|
188
|
+
def renderer
|
189
|
+
Gtk::CellRendererPixbuf.new
|
190
|
+
end
|
191
|
+
|
192
|
+
def attribute
|
193
|
+
:pixbuf
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
# pack multiple columns into one
|
198
|
+
class ActiveCompositeColumn < ActiveColumn
|
199
|
+
def initialize(name, opts={})
|
200
|
+
self.name = name
|
201
|
+
@virtual = true
|
202
|
+
@visible = true
|
203
|
+
end
|
204
|
+
def view
|
205
|
+
column
|
206
|
+
end
|
207
|
+
def add(child_column, expand=true)
|
208
|
+
raise ArgumentError, "give an ActiveColumn, not #{child_column.inspect}" unless child_column.is_a?(ActiveColumn)
|
209
|
+
child_column.hide!
|
210
|
+
rend = child_column.renderer
|
211
|
+
column.pack_start(rend, expand)
|
212
|
+
column.add_attribute(rend, child_column.attribute, child_column.id)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
|
217
|
+
end
|
218
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
module ActiveTreeStoreColumns
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
class_inheritable_accessor :column_id
|
6
|
+
write_inheritable_attribute :column_id, {}
|
7
|
+
class_inheritable_accessor :columns
|
8
|
+
write_inheritable_attribute :columns, []
|
9
|
+
include InstanceMethods
|
10
|
+
extend ClassMethods
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module InstanceMethods
|
15
|
+
def columns
|
16
|
+
self.class.columns
|
17
|
+
end
|
18
|
+
|
19
|
+
def data_columns
|
20
|
+
self.class.data_columns
|
21
|
+
end
|
22
|
+
|
23
|
+
def visible_columns
|
24
|
+
self.class.visible_columns
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
module ClassMethods
|
30
|
+
# options:
|
31
|
+
# :virtual: (bool )does not take actual values
|
32
|
+
# :visible: (bool) should be shown in the view
|
33
|
+
def column(label,type, opts={})
|
34
|
+
return columns[column_id[label.to_sym]] if column_id.has_key?(label.to_sym) # do not double-define
|
35
|
+
opts.reverse_merge!(:visible => true, :virtual => false)
|
36
|
+
index = column_count
|
37
|
+
column_id[label.to_sym] = index
|
38
|
+
col = ActiveColumn.create(index, label, type, opts)
|
39
|
+
columns << col
|
40
|
+
const_set label.to_s.upcase, index
|
41
|
+
class_eval <<-EOCODE
|
42
|
+
def self.#{label}_column
|
43
|
+
#{index}
|
44
|
+
end
|
45
|
+
EOCODE
|
46
|
+
return col
|
47
|
+
end
|
48
|
+
|
49
|
+
def composite_column(label)
|
50
|
+
col = ActiveCompositeColumn.new(label)
|
51
|
+
yield col
|
52
|
+
columns << col
|
53
|
+
return col
|
54
|
+
end
|
55
|
+
|
56
|
+
def virtual_column(label, type, opts={})
|
57
|
+
column label, type, opts.merge(:virtual => true)
|
58
|
+
end
|
59
|
+
|
60
|
+
# visible vs. virtual
|
61
|
+
def data_columns
|
62
|
+
columns.reject(&:virtual?)
|
63
|
+
end
|
64
|
+
|
65
|
+
def visible_columns
|
66
|
+
columns.select(&:visible?)
|
67
|
+
end
|
68
|
+
|
69
|
+
def invisible_columns
|
70
|
+
columns.reject(&:visible?)
|
71
|
+
end
|
72
|
+
|
73
|
+
def column_count
|
74
|
+
columns.size
|
75
|
+
end
|
76
|
+
|
77
|
+
def column_classes
|
78
|
+
columns.map(&:data_class)
|
79
|
+
end
|
80
|
+
|
81
|
+
def setup_column_id_constants
|
82
|
+
column_id.each do |sym, index|
|
83
|
+
const_set sym.to_s.upcase, index
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
module TreeStoreExtentions
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
include ActiveSupport::Callbacks
|
7
|
+
include ActiveTreeStoreColumns
|
8
|
+
include ActiveTreeStoreIndex
|
9
|
+
end
|
10
|
+
end
|
11
|
+
## associates a Gtk::TreeView widget with self (a tree model).
|
12
|
+
def apply_to_tree(treeview, opts={})
|
13
|
+
raise ArgumentError, "please provide a Gtk::TreeView" unless treeview.is_a?(Gtk::TreeView)
|
14
|
+
treeview.model = self
|
15
|
+
cols = self.class.visible_columns
|
16
|
+
cols = cols.except(opts[:except]) if opts.has_key?(:except)
|
17
|
+
cols = cols.slice(opts[:only]) if opts.has_key?(:only)
|
18
|
+
cols.map(&:view).each do |column|
|
19
|
+
treeview.append_column(column)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Populare the Tree with an array of objects. The Tree gets cleared first.
|
24
|
+
def populate(array)
|
25
|
+
clear
|
26
|
+
array.each do |element|
|
27
|
+
self.add element
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# The original object for +iter+.
|
32
|
+
# FIXME remove
|
33
|
+
def get_object(iter)
|
34
|
+
raise "depricated - please use iter[OBJECT]"
|
35
|
+
iter[ self.class.column_id[:object] ]
|
36
|
+
end
|
37
|
+
|
38
|
+
# Add +object+ to tree, give optional +parent+
|
39
|
+
def add(object, parent=nil)
|
40
|
+
iter = self.append parent
|
41
|
+
case object
|
42
|
+
when Hash
|
43
|
+
update_iter_from_hash iter, object
|
44
|
+
else
|
45
|
+
update_iter_from_object iter, object
|
46
|
+
end
|
47
|
+
iter[ self.class.column_id[:object] ] = object
|
48
|
+
iter
|
49
|
+
end
|
50
|
+
|
51
|
+
# Updates the display in the tree/list of the given object
|
52
|
+
def refresh(object)
|
53
|
+
each do |model,path,iter|
|
54
|
+
if iter[OBJECT] == object
|
55
|
+
update_iter_from_object(iter, object)
|
56
|
+
break
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
def update_iter_from_object(iter, object)
|
63
|
+
data_columns.each do |column|
|
64
|
+
iter[column.id] = column.data_value(object)
|
65
|
+
end
|
66
|
+
iter
|
67
|
+
end
|
68
|
+
def update_iter_from_hash(iter, hash = {})
|
69
|
+
hash.symbolize_keys.each do |key,value|
|
70
|
+
if id = self.class.column_id[key]
|
71
|
+
iter[ id ] = value
|
72
|
+
end
|
73
|
+
end
|
74
|
+
iter
|
75
|
+
end
|
76
|
+
|
77
|
+
def reference_for(iter)
|
78
|
+
Gtk::TreeRowReference.new(self, iter.path)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
module ActiveTreeStoreIndex
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
include InstanceMethods
|
6
|
+
extend ClassMethods
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module InstanceMethods
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def index_by(column)
|
15
|
+
by = %Q~by_#{column}~
|
16
|
+
raise "cannot index by #{column}, it is already applied" if public_instance_methods.include?("find_#{by}")
|
17
|
+
class_eval <<-EOCODE
|
18
|
+
def find_#{by}!(val)
|
19
|
+
find_#{by}(val) || raise("cannot find by #{column}: '\#{val}'")
|
20
|
+
end
|
21
|
+
def find_#{by}(val)
|
22
|
+
if ref = has_#{column}?(val)
|
23
|
+
self.get_iter(ref.path)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
def has_#{column}?(val)
|
27
|
+
index_#{by}[val]
|
28
|
+
end
|
29
|
+
def remember_iter_#{by}(iter)
|
30
|
+
val = iter[ self.class.column_id[:#{column}] ]
|
31
|
+
index_#{by}[val] = reference_for(iter)
|
32
|
+
end
|
33
|
+
def index_#{by}
|
34
|
+
@index_#{by} ||= {}
|
35
|
+
end
|
36
|
+
def add_with_index_#{by}(*args)
|
37
|
+
iter = add_without_index_#{by}(*args)
|
38
|
+
remember_iter_#{by}(iter)
|
39
|
+
iter
|
40
|
+
end
|
41
|
+
alias_method_chain :add, :index_#{by}
|
42
|
+
def remove_with_index_#{by}(iter)
|
43
|
+
index_#{by}.delete iter[ self.class.column_id[:#{column}] ]
|
44
|
+
remove_without_index_#{by}(iter)
|
45
|
+
end
|
46
|
+
alias_method_chain :remove, :index_#{by}
|
47
|
+
EOCODE
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ActiveWindow
|
2
|
+
class ActiveTreeStore < Gtk::TreeStore
|
3
|
+
include TreeStoreExtentions
|
4
|
+
virtual_column :visible, TrueClass, :visible => false
|
5
|
+
virtual_column :object, Object, :visible => false
|
6
|
+
define_callbacks :after_add
|
7
|
+
|
8
|
+
def initialize(opts={})
|
9
|
+
@initial_add_in_progress = false
|
10
|
+
super(*self.class.column_classes)
|
11
|
+
end
|
12
|
+
|
13
|
+
# disables some heavy calculations
|
14
|
+
def initial_adding
|
15
|
+
old_progress = initial_add_in_progress?
|
16
|
+
@initial_add_in_progress = true
|
17
|
+
yield
|
18
|
+
@initial_add_in_progress = old_progress
|
19
|
+
end
|
20
|
+
|
21
|
+
def initial_add_in_progress?
|
22
|
+
@initial_add_in_progress
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|