forked from danlucraft/redcar
/
speedbar.rb
270 lines (244 loc) · 8.29 KB
/
speedbar.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
module Redcar
class ApplicationSWT
class Speedbar
include Redcar::ReentryHelpers
attr_reader :widget
def initialize(window, parent, model)
@window_model = window
@parent = parent
@model = model
create_widgets
attach_key_listeners
disable_menu_items
if widget = focussable_widgets.first
widget.set_focus
end
@handlers = Hash.new {|h,k| h[k] = []}
@parent.layout
@model.after_draw if @model.respond_to?(:after_draw)
end
def close
@composite.dispose
@parent.layout
end
def disable_menu_items
key_strings = []
@model.__items.each do |i|
if i.respond_to?(:key)
key_strings << i.key
end
end
key_strings.uniq.each do |key_string|
ApplicationSWT::Menu.disable_items(key_string)
end
end
def num_columns
@model.__items.select {|i| !i.is_a?(Redcar::Speedbar::KeyItem) }.length
end
def key_items
@model.__items.select {|i| i.respond_to?(:key) and i.key }
end
def keyable_widgets
@keyable_widgets ||= []
end
def focussable_widgets
@focussable_widgets ||= []
end
def create_widgets
create_bar_widget
create_item_widgets
end
def create_bar_widget
@composite = Swt::Widgets::Composite.new(@parent, Swt::SWT::NONE)
grid_data = Swt::Layout::GridData.new
grid_data.grabExcessHorizontalSpace = true
grid_data.horizontalAlignment = Swt::Layout::GridData::FILL
@composite.setLayoutData(grid_data)
layout = Swt::Layout::GridLayout.new(num_columns + 1, false)
layout.verticalSpacing = 0
layout.marginHeight = 0
layout.marginTop = 5
@composite.setLayout(layout)
image = Swt::Graphics::Image.new(ApplicationSWT.display, Redcar::Speedbar.close_image_path)
label = Swt::Widgets::Label.new(@composite, 0)
label.set_image(image)
label.add_mouse_listener(MouseListener.new(self))
end
def execute_listener_in_model(item, *args)
if item.listener
begin
@model.instance_exec(*args, &item.listener)
rescue => err
error_in_listener(err)
end
end
end
def create_item_widgets
@model.__items.each do |item|
case item
when Redcar::Speedbar::LabelItem
label = Swt::Widgets::Label.new(@composite, 0)
label.set_text(item.text)
item.add_listener(:changed_text) do |new_text|
label.set_text(item.text)
end
when Redcar::Speedbar::TextBoxItem
edit_view = EditView.new
item.edit_view = edit_view
edit_view_swt = EditViewSWT.new(edit_view, @composite, :single_line => true)
mate_text = edit_view_swt.mate_text
mate_text.set_font(EditView.font, EditView.font_size)
mate_text.getControl.set_text(item.value)
mate_text.set_grammar_by_name "Ruby"
mate_text.set_theme_by_name(EditView.theme)
mate_text.set_root_scope_by_content_name("Ruby", "string.regexp.classic.ruby")
gridData = Swt::Layout::GridData.new
gridData.grabExcessHorizontalSpace = true
gridData.horizontalAlignment = Swt::Layout::GridData::FILL
mate_text.getControl.set_layout_data(gridData)
edit_view.document.add_listener(:changed) do
ignore(item.name) do
item.value = edit_view.document.to_s
execute_listener_in_model(item, item.value)
end
end
item.add_listener(:changed_value) do |new_value|
ignore(item.name) do
mate_text.getControl.set_text(new_value)
end
end
keyable_widgets << mate_text.getControl
focussable_widgets << mate_text.getControl
when Redcar::Speedbar::ButtonItem
button = Swt::Widgets::Button.new(@composite, 0)
button.set_text(item.text)
button.add_selection_listener do
execute_listener_in_model(item)
end
item.add_listener(:changed_text) do |new_text|
button.set_text(item.text)
end
keyable_widgets << button
focussable_widgets << button
when Redcar::Speedbar::ComboItem
combo = Swt::Widgets::Combo.new(@composite, Swt::SWT::READ_ONLY)
combo.items = item.items.to_java(:string)
if item.value
combo.select(item.items.index(item.value))
end
combo.add_selection_listener do
ignore(item.name) do
item.value = combo.text
execute_listener_in_model(item, item.value)
end
end
item.add_listener(:changed_items) do |new_items|
rescue_speedbar_errors do
ignore(item.name) do
combo.items = item.items.to_java(:string)
item.value = nil
end
end
end
item.add_listener(:changed_value) do |new_value|
rescue_speedbar_errors do
ignore(item.name) do
combo.select(item.items.index(item.value))
end
end
end
keyable_widgets << combo
focussable_widgets << combo
when Redcar::Speedbar::ToggleItem
button = Swt::Widgets::Button.new(@composite, Swt::SWT::CHECK)
button.set_text(item.text)
button.set_selection(!!item.value)
button.add_selection_listener do
item.value = button.get_selection
execute_listener_in_model(item, item.value)
end
item.add_listener(:changed_text) do |new_text|
rescue_speedbar_errors do
button.set_text = new_text
end
end
item.add_listener(:changed_value) do |new_value|
rescue_speedbar_errors do
button.set_selection(!!new_value)
end
end
keyable_widgets << button
focussable_widgets << button
end
end
end
class KeyListener
def initialize(speedbar)
@speedbar = speedbar
end
def key_pressed(e)
@speedbar.key_press(e)
end
def key_released(e)
end
end
class MouseListener
def initialize(speedbar)
@speedbar = speedbar
end
def mouse_down(*_); end
def mouse_up(*_)
@speedbar.close_pressed
end
def mouse_double_click(*_); end
end
def attach_key_listeners
keyable_widgets.each do |widget|
widget.add_key_listener(KeyListener.new(self))
end
end
def close_pressed
@window_model.close_speedbar
end
def key_press(e)
return if Application::Dialog.in_dialog?
key_string = Menu::BindingTranslator.key_string(e)
if key_string == "\e"
@window_model.close_speedbar
e.doit = false
end
key_items.each do |key_item|
if Menu::BindingTranslator.matches?(key_string, key_item.key)
e.doit = false
begin
@model.instance_exec(&key_item.listener)
rescue Object => err
error_in_listener(err)
end
end
end
end
def rescue_speedbar_errors
begin
yield
rescue Object => e
if e.class.name == "TestingError"
raise e
else
puts "*** Error in speedbar"
puts e.class.to_s + ": " + e.message
puts e.backtrace
end
end
end
def error_in_listener(e)
if e.class.name == "TestingError"
raise e
else
puts "*** Error in speedbar listener: #{e.message}"
puts e.backtrace.map {|l| " " + l}
end
end
end
end
end